Merge mozilla-inbound and mozilla-central

This commit is contained in:
Marco Bonardo 2011-07-08 11:53:56 +02:00
Родитель f7ab5bb59c eed812e90e
Коммит f3c1fffe53
114 изменённых файлов: 2201 добавлений и 279 удалений

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

@ -9,7 +9,7 @@ pref("app.update.interval", 28800);
pref("app.update.download.backgroundInterval", 60);
// URL user can browse to manually if for some reason all update installation
// attempts fail.
pref("app.update.url.manual", "http://nightly.mozilla.org/");
pref("app.update.url.manual", "http://www.mozilla.com/firefox/channel/");
// A default value for the "More information about this update" link
// supplied in the "An update is available" page of the update wizard.
pref("app.update.url.details", "http://www.mozilla.org/projects/%APP%/");

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

@ -39,6 +39,7 @@ class DeviceManagerADB(DeviceManager):
def mkDir(self, name):
try:
self.checkCmd(["shell", "mkdir", name])
self.chmodDir(name)
return name
except:
return None

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

@ -515,7 +515,6 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, PRBool aClone, PRBool aDeep,
nsnull;
nsCOMPtr<nsINode> clone;
PRBool isDeepDocumentClone = PR_FALSE;
if (aClone) {
rv = aNode->Clone(nodeInfo, getter_AddRefs(clone));
NS_ENSURE_SUCCESS(rv, rv);
@ -528,7 +527,6 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNode, PRBool aClone, PRBool aDeep,
NS_ENSURE_SUCCESS(rv, rv);
}
else if (aDeep && clone->IsNodeOfType(nsINode::eDOCUMENT)) {
isDeepDocumentClone = PR_TRUE;
// After cloning the document itself, we want to clone the children into
// the cloned document (somewhat like cloning and importing them into the
// cloned document).

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

@ -502,6 +502,7 @@ _TEST_FILES2 = \
somedatas.resource \
somedatas.resource^headers^ \
delayedServerEvents.sjs \
test_bug664916.html \
test_bug666604.html \
$(NULL)

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

@ -0,0 +1,40 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=664916
-->
<head>
<title>Test for Bug 664916</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=664916">Mozilla Bug 664916</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 664916 **/
var div = document.createElement("div");
var textNode = document.createTextNode("x")
var tagNameGetter = div.__lookupGetter__("tagName");
var tagName = "";
try {
tagName = tagNameGetter.call(textNode);
ok(false, "Should throw when calling tagname getter on text node");
} catch(e) {
ok(true, "Should throw when calling tagname getter on text node");
}
is(tagName, "", "Should not have changed tagName yet");
tagName = tagNameGetter.call(div);
is(tagName, "DIV", "Should get the right tag name");
</script>
</pre>
</body>
</html>

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

@ -649,9 +649,9 @@ ImageDocument::CreateSyntheticDocument()
// This is bad during printing, it means tall image frames won't know
// the size of the paper and cannot break into continuations along
// multiple pages.
Element* head = GetHeadElement();
if (!head) {
NS_WARNING("no head on image document!");
Element* body = GetBodyElement();
if (!body) {
NS_WARNING("no body on image document!");
return NS_ERROR_FAILURE;
}
@ -665,16 +665,10 @@ ImageDocument::CreateSyntheticDocument()
return NS_ERROR_OUT_OF_MEMORY;
}
styleContent->SetInnerHTML(NS_LITERAL_STRING("img { display: block; }"));
head->AppendChildTo(styleContent, PR_FALSE);
styleContent->SetTextContent(NS_LITERAL_STRING("img { display: block; }"));
body->AppendChildTo(styleContent, PR_FALSE);
// Add the image element
Element* body = GetBodyElement();
if (!body) {
NS_WARNING("no body on image document!");
return NS_ERROR_FAILURE;
}
nodeInfo = mNodeInfoManager->GetNodeInfo(nsGkAtoms::img, nsnull,
kNameSpaceID_XHTML,
nsIDOMNode::ELEMENT_NODE);

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

@ -2170,16 +2170,8 @@ nsHTMLDocument::GetEmbeds(nsIDOMHTMLCollection** aEmbeds)
}
NS_IMETHODIMP
nsHTMLDocument::GetSelection(nsAString& aReturn)
nsHTMLDocument::GetSelection(nsISelection** aReturn)
{
aReturn.Truncate();
nsCOMPtr<nsIJSContextStack> stack = do_GetService("@mozilla.org/js/xpc/ContextStack;1");
JSContext* ccx = nsnull;
if (stack && NS_SUCCEEDED(stack->Peek(&ccx)) && ccx) {
JS_ReportWarning(ccx, "Deprecated method document.getSelection() called. Please use window.getSelection() instead.");
}
nsCOMPtr<nsIDOMWindow> window = do_QueryInterface(GetScopeObject());
nsCOMPtr<nsPIDOMWindow> pwin = do_QueryInterface(window);
NS_ENSURE_TRUE(pwin, NS_OK);
@ -2188,17 +2180,8 @@ nsHTMLDocument::GetSelection(nsAString& aReturn)
pwin->GetOuterWindow()->GetCurrentInnerWindow() == pwin,
NS_OK);
nsCOMPtr<nsISelection> selection;
nsresult rv = window->GetSelection(getter_AddRefs(selection));
NS_ENSURE_TRUE(selection && NS_SUCCEEDED(rv), rv);
nsXPIDLString str;
rv = selection->ToString(getter_Copies(str));
aReturn.Assign(str);
return rv;
return window->GetSelection(aReturn);
}
NS_IMETHODIMP

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

@ -124,7 +124,7 @@ DOMSVGAnimatedLengthList::InternalBaseValListWillChangeTo(const SVGLengthList& a
nsRefPtr<DOMSVGAnimatedLengthList> kungFuDeathGrip;
if (mBaseVal) {
if (!aNewValue.Length()) {
if (aNewValue.Length() < mBaseVal->Length()) {
// InternalListLengthWillChange might clear last reference to |this|.
// Retain a temporary reference to keep from dying before returning.
kungFuDeathGrip = this;

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

@ -123,7 +123,7 @@ DOMSVGAnimatedNumberList::InternalBaseValListWillChangeTo(const SVGNumberList& a
nsRefPtr<DOMSVGAnimatedNumberList> kungFuDeathGrip;
if (mBaseVal) {
if (!aNewValue.Length()) {
if (aNewValue.Length() < mBaseVal->Length()) {
// InternalListLengthWillChange might clear last reference to |this|.
// Retain a temporary reference to keep from dying before returning.
kungFuDeathGrip = this;

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

@ -119,7 +119,7 @@ DOMSVGLengthList::InternalListLengthWillChange(PRUint32 aNewLength)
}
nsRefPtr<DOMSVGLengthList> kungFuDeathGrip;
if (oldLength && !aNewLength) {
if (aNewLength < oldLength) {
// RemovingFromList() might clear last reference to |this|.
// Retain a temporary reference to keep from dying before returning.
kungFuDeathGrip = this;

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

@ -119,7 +119,7 @@ DOMSVGNumberList::InternalListLengthWillChange(PRUint32 aNewLength)
}
nsRefPtr<DOMSVGNumberList> kungFuDeathGrip;
if (oldLength && !aNewLength) {
if (aNewLength < oldLength) {
// RemovingFromList() might clear last reference to |this|.
// Retain a temporary reference to keep from dying before returning.
kungFuDeathGrip = this;

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

@ -156,7 +156,7 @@ DOMSVGPathSegList::InternalListWillChangeTo(const SVGPathData& aNewValue)
PRUint32 newSegType;
nsRefPtr<DOMSVGPathSegList> kungFuDeathGrip;
if (length && aNewValue.IsEmpty()) {
if (aNewValue.Length() < length) {
// RemovingFromList() might clear last reference to |this|.
// Retain a temporary reference to keep from dying before returning.
kungFuDeathGrip = this;

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

@ -148,7 +148,7 @@ DOMSVGPointList::InternalListWillChangeTo(const SVGPointList& aNewValue)
}
nsRefPtr<DOMSVGPointList> kungFuDeathGrip;
if (oldLength && !newLength) {
if (newLength < oldLength) {
// RemovingFromList() might clear last reference to |this|.
// Retain a temporary reference to keep from dying before returning.
kungFuDeathGrip = this;

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

@ -9192,7 +9192,17 @@ nsresult nsDocShell::DoChannelLoad(nsIChannel * aChannel,
// Load attributes depend on load type...
switch (mLoadType) {
case LOAD_HISTORY:
loadFlags |= nsIRequest::VALIDATE_NEVER;
{
// Only send VALIDATE_NEVER if mLSHE's URI was never changed via
// push/replaceState (bug 669671).
PRBool uriModified = PR_FALSE;
if (mLSHE) {
mLSHE->GetURIWasModified(&uriModified);
}
if (!uriModified)
loadFlags |= nsIRequest::VALIDATE_NEVER;
}
break;
case LOAD_RELOAD_CHARSET_CHANGE:
@ -9854,6 +9864,15 @@ nsDocShell::AddState(nsIVariant *aData, const nsAString& aTitle,
newSHEntry->SetStateData(scContainer);
newSHEntry->SetPostData(nsnull);
// If this push/replaceState changed the document's current URI and the new
// URI differs from the old URI in more than the hash, or if the old
// SHEntry's URI was modified in this way by a push/replaceState call
// set URIWasModified to true for the current SHEntry (bug 669671).
PRBool sameExceptHashes = PR_TRUE, oldURIWasModified = PR_FALSE;
newURI->EqualsExceptRef(mCurrentURI, &sameExceptHashes);
oldOSHE->GetURIWasModified(&oldURIWasModified);
newSHEntry->SetURIWasModified(!sameExceptHashes || oldURIWasModified);
// Step 5: If aReplace is false, indicating that we're doing a pushState
// rather than a replaceState, notify bfcache that we've added a page to
// the history so it can evict content viewers if appropriate.

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

@ -59,7 +59,7 @@ class nsDocShellEditorData;
[ptr] native nsDocShellEditorDataPtr(nsDocShellEditorData);
[scriptable, uuid(5f3ebf43-6944-45fb-b1b1-78a05bf9370b)]
[scriptable, uuid(b92d403e-f5ec-4b81-b0e3-6e6c241cef2d)]
interface nsISHEntry : nsIHistoryEntry
{
/** URI for the document */
@ -169,6 +169,19 @@ interface nsISHEntry : nsIHistoryEntry
* is a session history entry for
*/
attribute ACString contentType;
/**
* If we created this SHEntry via history.pushState or modified it via
* history.replaceState, and if we changed the SHEntry's URI via the
* push/replaceState call, and if the SHEntry's new URI differs from its
* old URI by more than just the hash, then we set this field to true.
*
* Additionally, if this SHEntry was created by calling pushState from a
* SHEntry whose URI was modified, this SHEntry's URIWasModified field is
* true.
*
*/
attribute boolean URIWasModified;
/** Set/Get scrollers' positon in anchored pages */
void setScrollPosition(in long x, in long y);

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

@ -108,6 +108,7 @@ nsSHEntry::nsSHEntry()
, mDocIdentifier(gEntryDocIdentifier++)
, mScrollPositionX(0)
, mScrollPositionY(0)
, mURIWasModified(PR_FALSE)
, mIsFrameNavigation(PR_FALSE)
, mSaveLayoutState(PR_TRUE)
, mExpired(PR_FALSE)
@ -132,6 +133,7 @@ nsSHEntry::nsSHEntry(const nsSHEntry &other)
, mDocIdentifier(other.mDocIdentifier)
, mScrollPositionX(0) // XXX why not copy?
, mScrollPositionY(0) // XXX why not copy?
, mURIWasModified(other.mURIWasModified)
, mIsFrameNavigation(other.mIsFrameNavigation)
, mSaveLayoutState(other.mSaveLayoutState)
, mExpired(other.mExpired)
@ -208,6 +210,18 @@ NS_IMETHODIMP nsSHEntry::GetScrollPosition(PRInt32 *x, PRInt32 *y)
return NS_OK;
}
NS_IMETHODIMP nsSHEntry::GetURIWasModified(PRBool* aOut)
{
*aOut = mURIWasModified;
return NS_OK;
}
NS_IMETHODIMP nsSHEntry::SetURIWasModified(PRBool aIn)
{
mURIWasModified = aIn;
return NS_OK;
}
NS_IMETHODIMP nsSHEntry::GetURI(nsIURI** aURI)
{
*aURI = mURI;

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

@ -102,6 +102,7 @@ private:
PRInt64 mDocIdentifier;
PRInt32 mScrollPositionX;
PRInt32 mScrollPositionY;
PRPackedBool mURIWasModified;
PRPackedBool mIsFrameNavigation;
PRPackedBool mSaveLayoutState;
PRPackedBool mExpired;

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

@ -116,6 +116,8 @@ _TEST_FILES = \
test_bug668513.html \
bug668513_redirect.html \
bug668513_redirect.html^headers^ \
test_bug669671.html \
file_bug669671.sjs \
$(NULL)
ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)

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

@ -0,0 +1,13 @@
function handleRequest(request, response)
{
var count = parseInt(getState('count'));
if (!count)
count = 0;
setState('count', count + 1 + '');
response.setHeader('Content-Type', 'text/html', false);
response.setHeader('Cache-Control', 'max-age=0');
response.write('<html><body onload="opener.onChildLoad()" ' +
'onunload="parseInt(\'0\')">' +
count + '</body></html>');
}

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

@ -0,0 +1,140 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=669671
-->
<head>
<title>Test for Bug 669671</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=669671">Mozilla Bug 669671</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript;version=1.7">
/**
* Test for Bug 669671.
*
* This is a bit complicated. We have a script, file_bug669671.sjs, which counts
* how many times it's loaded and returns that count in the body of an HTML
* document. For brevity, call this page X.
*
* X is sent with Cache-Control: max-age=0 and can't be bfcached (it has an
* onunload handler). Our test does the following in a popup:
*
* 1) Load X?pushed, to prime the cache.
* 2) Navigate to X.
* 3) Call pushState and navigate from X to X?pushed.
* 4) Navigate to X?navigated.
* 5) Go back (to X?pushed).
*
* We do all this work so we can check that in step 5, we fetch X?pushed from
* the network -- we shouldn't use our cached copy, because of the
* cache-control header X sends.
*
* Then we go back and repeat the whole process but call history.replaceState
* instead of pushState. And for good measure, we test once more, this time
* modifying only the hash of the URI using replaceState. In this case, we
* *should* load from the cache.
*
**/
SimpleTest.waitForExplicitFinish();
function onChildLoad()
{
SimpleTest.executeSoon(function() { gGen.next() });
}
var _loadCount = 0;
function checkPopupLoadCount()
{
is(popup.document.body.innerHTML, _loadCount + '', 'Load count');
// We normally want to increment _loadCount here. But if the test fails
// because we didn't do a load we should have, let's not cause a cascade of
// failures by incrementing _loadCount.
var origCount = _loadCount;
if (popup.document.body.innerHTML >= _loadCount + '')
_loadCount++;
return origCount;
}
function test()
{
// Step 1 - The popup's body counts how many times we've requested the
// resource. This is the first time we've requested it, so it should be '0'.
checkPopupLoadCount();
// Step 2 - We'll get another onChildLoad when this finishes.
popup.location = 'file_bug669671.sjs';
yield;
// Step 3 - Call pushState and change the URI back to ?pushed.
checkPopupLoadCount();
popup.history.pushState('', '', '?pushed');
// Step 4 - Navigate away. This should trigger another onChildLoad.
popup.location = 'file_bug669671.sjs?navigated-1';
yield;
// Step 5 - Go back. This should result in another onload (because the file is
// not in bfcache) and should be the fourth time we've requested the sjs file.
checkPopupLoadCount();
popup.back();
yield;
// This is the check which was failing before we fixed the bug.
checkPopupLoadCount();
popup.close();
// Do the whole thing again, but with replaceState.
popup = window.open('file_bug669671.sjs?replaced');
yield;
checkPopupLoadCount();
popup.location = 'file_bug669671.sjs';
yield;
checkPopupLoadCount();
popup.history.replaceState('', '', '?replaced');
popup.location = 'file_bug669671.sjs?navigated-2';
yield;
checkPopupLoadCount();
popup.back();
yield;
checkPopupLoadCount();
popup.close();
// Once more, with feeling. Notice that we don't have to prime the cache
// with an extra load here, because X and X#hash share the same cache entry.
popup = window.open('file_bug669671.sjs?hash-test');
yield;
var initialCount = checkPopupLoadCount();
popup.history.replaceState('', '', '#hash');
popup.location = 'file_bug669671.sjs?navigated-3';
yield;
checkPopupLoadCount();
popup.back();
yield;
is(popup.document.body.innerHTML, initialCount + '',
'Load count (should be cached)');
popup.close();
SimpleTest.finish();
yield;
}
// This will call into onChildLoad once it loads.
var popup = window.open('file_bug669671.sjs?pushed');
var gGen = test();
</script>
</pre>
</body>
</html>

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

@ -54,31 +54,31 @@ nsDOMMemoryReporter::Init()
}
NS_IMETHODIMP
nsDOMMemoryReporter::GetProcess(char** aProcess)
nsDOMMemoryReporter::GetProcess(nsACString &aProcess)
{
// "" means the main process.
*aProcess = strdup("");
aProcess.Truncate();
return NS_OK;
}
NS_IMETHODIMP
nsDOMMemoryReporter::GetPath(char** aMemoryPath)
nsDOMMemoryReporter::GetPath(nsACString &aMemoryPath)
{
*aMemoryPath = strdup("explicit/dom");
aMemoryPath.AssignLiteral("explicit/dom");
return NS_OK;
}
NS_IMETHODIMP
nsDOMMemoryReporter::GetKind(int* aKind)
nsDOMMemoryReporter::GetKind(PRInt32* aKind)
{
*aKind = KIND_HEAP;
return NS_OK;
}
NS_IMETHODIMP
nsDOMMemoryReporter::GetDescription(char** aDescription)
nsDOMMemoryReporter::GetDescription(nsACString &aDescription)
{
*aDescription = strdup("Memory used by the DOM.");
aDescription.AssignLiteral("Memory used by the DOM.");
return NS_OK;
}

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

@ -44,16 +44,10 @@
class nsDOMMemoryReporter: public nsIMemoryReporter {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIMEMORYREPORTER
static void Init();
NS_IMETHOD GetProcess(char** aProcess);
NS_IMETHOD GetPath(char** aMemoryPath);
NS_IMETHOD GetKind(int* aKnd);
NS_IMETHOD GetDescription(char** aDescription);
NS_IMETHOD GetUnits(PRInt32* aUnits);
NS_IMETHOD GetAmount(PRInt64* aAmount);
private:
// Protect ctor, use Init() instead.
nsDOMMemoryReporter();

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

@ -185,7 +185,10 @@ static PRTime sMaxChromeScriptRunTime;
static nsIScriptSecurityManager *sSecurityManager;
// nsMemoryPressureObserver observes the memory-pressure notifications
// and forces a garbage collection and cycle collection when it happens.
// and forces a garbage collection and cycle collection when it happens, if
// the appropriate pref is set.
static PRBool sGCOnMemoryPressure;
class nsMemoryPressureObserver : public nsIObserver
{
@ -200,8 +203,10 @@ NS_IMETHODIMP
nsMemoryPressureObserver::Observe(nsISupports* aSubject, const char* aTopic,
const PRUnichar* aData)
{
nsJSContext::GarbageCollectNow();
nsJSContext::CycleCollectNow();
if (sGCOnMemoryPressure) {
nsJSContext::GarbageCollectNow();
nsJSContext::CycleCollectNow();
}
return NS_OK;
}
@ -3795,6 +3800,10 @@ nsJSRuntime::Init()
if (!obs)
return NS_ERROR_FAILURE;
Preferences::AddBoolVarCache(&sGCOnMemoryPressure,
"javascript.options.gc_on_memory_pressure",
PR_TRUE);
nsIObserver* memPressureObserver = new nsMemoryPressureObserver();
NS_ENSURE_TRUE(memPressureObserver, NS_ERROR_OUT_OF_MEMORY);
obs->AddObserver(memPressureObserver, "memory-pressure", PR_FALSE);

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

@ -49,8 +49,9 @@
*
* @see <http://www.whatwg.org/html/>
*/
interface nsISelection;
[scriptable, uuid(3c0ca40f-72c5-4d15-935e-ccaff7953f2c)]
[scriptable, uuid(3ab3e856-361d-435a-8a4d-b462799945cd)]
interface nsIDOMHTMLDocument : nsIDOMDocument
{
readonly attribute DOMString URL;
@ -132,7 +133,7 @@ interface nsIDOMHTMLDocument : nsIDOMDocument
// DOM Range
DOMString getSelection();
nsISelection getSelection();
// Mozilla extensions

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

@ -363,11 +363,11 @@ ContentChild::RecvPMemoryReportRequestConstructor(PMemoryReportRequestChild* chi
PRInt32 units;
PRInt64 amount;
nsCString desc;
r->GetPath(getter_Copies(path));
r->GetPath(path);
r->GetKind(&kind);
r->GetUnits(&units);
r->GetAmount(&amount);
r->GetDescription(getter_Copies(desc));
r->GetDescription(desc);
MemoryReport memreport(process, path, kind, units, amount, desc);
reports.AppendElement(memreport);

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

@ -89,6 +89,7 @@
<action android:name="org.mozilla.gecko.restart"/>
</intent-filter>
</activity>
#if MOZ_CRASHREPORTER
<activity android:name="CrashReporter"
android:label="@string/crash_reporter_title"
@ -98,5 +99,14 @@
</intent-filter>
</activity>
#endif
<activity android:name="LauncherShortcuts"
android:label="@string/launcher_shortcuts_title">
<!-- This intent-filter allows your shortcuts to be created in the launcher. -->
<intent-filter>
<action android:name="android.intent.action.CREATE_SHORTCUT" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
</manifest>

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

@ -303,7 +303,7 @@ abstract public class GeckoApp
Log.i("GeckoApp", "Intent : ACTION_MAIN");
GeckoAppShell.sendEventToGecko(new GeckoEvent(""));
}
else if (action.equals("org.mozilla.fennec.WEBAPP")) {
else if (action.equals("org.mozilla.gecko.WEBAPP")) {
String uri = intent.getStringExtra("args");
GeckoAppShell.sendEventToGecko(new GeckoEvent(uri));
Log.i("GeckoApp","Intent : WEBAPP - " + uri);

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

@ -678,7 +678,7 @@ public class GeckoAppShell
Log.w("GeckoAppJava", "installWebApplication for " + aURI + " [" + aTitle + "]");
// the intent to be launched by the shortcut
Intent shortcutIntent = new Intent("org.mozilla.fennec.WEBAPP");
Intent shortcutIntent = new Intent("org.mozilla.gecko.WEBAPP");
shortcutIntent.setClassName(GeckoApp.mAppContext,
GeckoApp.mAppContext.getPackageName() + ".App");
shortcutIntent.putExtra("args", "--webapp=" + aURI);

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

@ -0,0 +1,184 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* ***** 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 Android code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Vladimir Vukicevic <vladimir@pobox.com>
* Wes Johnston <wjohnston@mozilla.com>
* Mark Finkle <mfinkle@mozilla.com>
*
* 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 ***** */
#filter substitution
package @ANDROID_PACKAGE_NAME@;
import java.io.*;
import org.mozilla.gecko.*;
import android.os.*;
import android.content.*;
import android.app.*;
import android.text.*;
import android.util.*;
import android.widget.*;
import android.database.sqlite.*;
import android.database.*;
import android.view.*;
import android.net.Uri;
import android.graphics.*;
public class LauncherShortcuts extends ListActivity {
public static final String CREATE_SHORTCUT = "org.mozilla.gecko.CREATE_SHORTCUT";
public class LauncherCursorAdapter extends SimpleCursorAdapter {
private Cursor _cursor;
private Context _context;
public LauncherCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
// Using the older, deprecated constructor so we can work on API < 11
super(context, layout, c, from, to);
_cursor = c;
_context = context;
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
ImageView imageView = (ImageView) view.findViewById(R.id.favicon);
String favicon = cursor.getString(3);
byte[] raw = Base64.decode(favicon.substring(22), Base64.DEFAULT);
Bitmap bitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeByteArray(raw, 0, raw.length), 48, 48, true);
imageView.setImageBitmap(bitmap);
super.bindView(view, context, cursor);
}
}
private Cursor getCursor(Context context) {
File home = new File(context.getFilesDir(), "mozilla");
if (!home.exists())
return null;
File profile = null;
String[] files = home.list();
for (int i = 0; i < files.length; i++) {
if (files[i].endsWith(".default")) {
profile = new File(home, files[i]);
break;
}
}
if (profile == null)
return null;
File webapps = new File(profile, "webapps.sqlite");
if (!webapps.exists())
return null;
Log.i("LauncherShortcuts", "Opening: " + webapps.getPath());
mDb = SQLiteDatabase.openDatabase(webapps.getPath(), null, SQLiteDatabase.OPEN_READONLY | SQLiteDatabase.NO_LOCALIZED_COLLATORS);
return mDb.rawQuery("SELECT rowid as _id, title, uri, icon FROM webapps", null);
}
private Cursor mCursor;
private SQLiteDatabase mDb;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.launch_app_list);
final Intent intent = getIntent();
final String action = intent.getAction();
if (Intent.ACTION_CREATE_SHORTCUT.equals(action)) {
mCursor = getCursor(this);
if (mCursor != null) {
// After selecting an item, the empty view can flash on screen. Clear
// the text so we don't see it.
TextView emptyText = (TextView)findViewById(android.R.id.empty);
emptyText.setText("");
// Load the list using a custom adapter so we can create the bitmaps
ListAdapter adapter = new LauncherCursorAdapter(
this,
R.layout.launch_app_listitem,
mCursor,
new String[] {"title"},
new int[] {R.id.title}
);
setListAdapter(adapter);
}
}
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
mCursor.moveToPosition(position);
Intent shortcutintent = new Intent("org.mozilla.gecko.WEBAPP");
shortcutintent.setClass(this, App.class);
shortcutintent.putExtra("args", "--webapp=" + mCursor.getString(2));
Intent intent = new Intent();
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, mCursor.getString(1));
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutintent);
String favicon = mCursor.getString(3);
byte[] raw = Base64.decode(favicon.substring(22), Base64.DEFAULT);
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int size;
switch (dm.densityDpi) {
case DisplayMetrics.DENSITY_MEDIUM:
size = 48;
break;
case DisplayMetrics.DENSITY_HIGH:
size = 72;
break;
default:
size = 72;
}
Bitmap bitmap = Bitmap.createScaledBitmap(BitmapFactory.decodeByteArray(raw, 0, raw.length), size, size, true);
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, bitmap);
// Now, return the result to the launcher
setResult(RESULT_OK, intent);
mDb.close();
mCursor.close();
finish();
}
}

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

@ -59,6 +59,7 @@ PROCESSEDJAVAFILES = \
App.java \
Restarter.java \
NotificationHandler.java \
LauncherShortcuts.java \
$(NULL)
@ -116,6 +117,8 @@ RES_LAYOUT = \
res/layout/notification_progress.xml \
res/layout/notification_progress_text.xml \
res/layout/notification_icon_text.xml \
res/layout/launch_app_list.xml \
res/layout/launch_app_listitem.xml \
$(NULL)
RES_VALUES = res/values/colors.xml res/values/themes.xml

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

@ -16,3 +16,6 @@
<!ENTITY sending_crash_report "Sending crash report\u2026">
<!ENTITY exit_label "Exit">
<!ENTITY continue_label "Continue">
<!ENTITY launcher_shortcuts_title "&brandShortName; Web Apps">
<!ENTITY launcher_shortcuts_empty "No web apps were found">

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

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="3dip"
android:orientation="vertical"
android:windowIsFloating="true">
<ListView android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:drawSelectorOnTop="false"/>
<TextView android:id="@android:id/empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/launcher_shortcuts_empty"/>
</LinearLayout>

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

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:padding="6dip"
android:orientation="horizontal">
<ImageView
android:id="@+id/favicon"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginRight="6dip"/>
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"/>
</LinearLayout>

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

@ -21,4 +21,7 @@
<string name="sending_crash_report">&sending_crash_report;</string>
<string name="exit_label">&exit_label;</string>
<string name="continue_label">&continue_label;</string>
<string name="launcher_shortcuts_title">&launcher_shortcuts_title;</string>
<string name="launcher_shortcuts_empty">&launcher_shortcuts_empty;</string>
</resources>

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

@ -600,13 +600,13 @@ public:
NS_DECL_ISUPPORTS
NS_IMETHOD GetProcess(char **process) {
*process = strdup("");
NS_IMETHOD GetProcess(nsACString &process) {
process.Truncate();
return NS_OK;
}
NS_IMETHOD GetPath(char **memoryPath) {
*memoryPath = strdup(SurfaceMemoryReporterPathForType(mType));
NS_IMETHOD GetPath(nsACString &path) {
path.Assign(SurfaceMemoryReporterPathForType(mType));
return NS_OK;
}
@ -625,8 +625,8 @@ public:
return NS_OK;
}
NS_IMETHOD GetDescription(char **desc) {
*desc = strdup("Memory used by gfx surface of the given type.");
NS_IMETHOD GetDescription(nsACString &desc) {
desc.AssignLiteral("Memory used by gfx surface of the given type.");
return NS_OK;
}

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

@ -481,8 +481,10 @@ bool Channel::ChannelImpl::ProcessIncomingMessages() {
// Process messages from input buffer.
const char *p;
const char *overflowp;
const char *end;
if (input_overflow_buf_.empty()) {
overflowp = NULL;
p = input_buf_;
end = p + bytes_read;
} else {
@ -493,7 +495,7 @@ bool Channel::ChannelImpl::ProcessIncomingMessages() {
return false;
}
input_overflow_buf_.append(input_buf_, bytes_read);
p = input_overflow_buf_.data();
overflowp = p = input_overflow_buf_.data();
end = p + input_overflow_buf_.size();
}
@ -571,7 +573,15 @@ bool Channel::ChannelImpl::ProcessIncomingMessages() {
break;
}
}
input_overflow_buf_.assign(p, end - p);
if (end == p) {
input_overflow_buf_.clear();
} else if (!overflowp) {
// p is from input_buf_
input_overflow_buf_.assign(p, end - p);
} else if (p > overflowp) {
// p is from input_overflow_buf_
input_overflow_buf_.erase(0, p - overflowp);
}
input_overflow_fds_ = std::vector<int>(&fds[fds_i], &fds[num_fds]);
// When the input data buffer is empty, the overflow fds should be too. If

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

@ -40,6 +40,7 @@
#include <math.h>
#include "nsString.h"
#include "nsIMemoryReporter.h"
#include "mozilla/ipc/SharedMemory.h"

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

@ -150,6 +150,7 @@ CPPSRCS = \
jsgcmark.cpp \
jsgcchunk.cpp \
jsgcstats.cpp \
jscrashreport.cpp \
jshash.cpp \
jsinterp.cpp \
jsinvoke.cpp \
@ -206,6 +207,7 @@ INSTALLED_HEADERS = \
jsclone.h \
jscntxt.h \
jscompat.h \
jscrashreport.h \
jsdate.h \
jsdbgapi.h \
jsdhash.h \

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

@ -1183,6 +1183,16 @@ extern JS_PUBLIC_API(JSBool)
JS_SetCTypesCallbacks(JSContext *cx, JSObject *ctypesObj, JSCTypesCallbacks *callbacks);
#endif
typedef JSBool
(* JSEnumerateDiagnosticMemoryCallback)(void *ptr, size_t length);
/*
* Enumerate memory regions that contain diagnostic information
* intended to be included in crash report minidumps.
*/
extern JS_PUBLIC_API(void)
JS_EnumerateDiagnosticMemoryRegions(JSEnumerateDiagnosticMemoryCallback callback);
/*
* Macros to hide interpreter stack layout details from a JSFastNative using
* its jsval *vp parameter. The stack layout underlying invocation can't change

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

@ -412,6 +412,12 @@ struct JSRuntime {
/* Compartment that is currently involved in per-compartment GC */
JSCompartment *gcCurrentCompartment;
/*
* If this is non-NULL, all marked objects must belong to this compartment.
* This is used to look for compartment bugs.
*/
JSCompartment *gcCheckCompartment;
/*
* We can pack these flags as only the GC thread writes to them. Atomic
* updates to packed bytes are not guaranteed, so stores issued by one

111
js/src/jscrashformat.h Normal file
Просмотреть файл

@ -0,0 +1,111 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=4 sw=4 et tw=99:
*
* ***** 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 SpiderMonkey JavaScript 1.9 code, released
* May 28, 2008.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of 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 ***** */
#ifndef jscrashformat_h___
#define jscrashformat_h___
#include <string.h>
namespace js {
namespace crash {
const static int crash_cookie_len = 16;
const static char crash_cookie[crash_cookie_len] = "*J*S*CRASHDATA*";
/* These values are used for CrashHeader::id. */
enum {
JS_CRASH_STACK_GC = 0x400,
JS_CRASH_STACK_ERROR = 0x401,
JS_CRASH_RING = 0x800
};
/*
* All the data here will be stored directly in the minidump, so we use
* platform-independent types. We also ensure that the size of every field is a
* multiple of 8 bytes, to guarantee that they won't be padded.
*/
struct CrashHeader
{
char cookie[crash_cookie_len];
/* id of the crash data, chosen from the enum above. */
uint64 id;
CrashHeader(uint64 id) : id(id) { memcpy(cookie, crash_cookie, crash_cookie_len); }
};
struct CrashRegisters
{
uint64 ip, sp, bp;
};
const static int crash_buffer_size = 32 * 1024;
struct CrashStack
{
CrashStack(uint64 id) : header(id) {}
CrashHeader header;
uint64 snaptime; /* Unix time when the stack was snapshotted. */
CrashRegisters regs; /* Register contents for the snapshot. */
uint64 stack_base; /* Base address of stack at the time of snapshot. */
uint64 stack_len; /* Extent of the stack. */
char stack[crash_buffer_size]; /* Contents of the stack. */
};
struct CrashRing
{
CrashRing(uint64 id) : header(id), offset(0) { memset(buffer, 0, sizeof(buffer)); }
CrashHeader header;
uint64 offset; /* Next byte to be written in the buffer. */
char buffer[crash_buffer_size];
};
/* These are the tag values for each entry in the CrashRing. */
enum {
JS_CRASH_TAG_GC = 0x200
};
} /* namespace crash */
} /* namespace js */
#endif

280
js/src/jscrashreport.cpp Normal file
Просмотреть файл

@ -0,0 +1,280 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=4 sw=4 et tw=99:
*
* ***** 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 SpiderMonkey JavaScript 1.9 code, released
* May 28, 2008.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of 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 "jsapi.h"
#include "jscntxt.h"
#include "jscrashreport.h"
#include "jscrashformat.h"
#include <time.h>
namespace js {
namespace crash {
const static int stack_snapshot_max_size = 32768;
#if defined(XP_WIN)
#include <Windows.h>
static bool
GetStack(uint64 *stack, uint64 *stack_len, CrashRegisters *regs, char *buffer, size_t size)
{
/* Try to figure out how big the stack is. */
char dummy;
MEMORY_BASIC_INFORMATION info;
if (VirtualQuery(reinterpret_cast<LPCVOID>(&dummy), &info, sizeof(info)) == 0)
return false;
if (info.State != MEM_COMMIT)
return false;
/* 256 is a fudge factor to account for the rest of GetStack's frame. */
uint64 p = uint64(&dummy) - 256;
uint64 len = stack_snapshot_max_size;
if (p + len > uint64(info.BaseAddress) + info.RegionSize)
len = uint64(info.BaseAddress) + info.RegionSize - p;
if (len > size)
len = size;
*stack = p;
*stack_len = len;
/* Get the register state. */
#if JS_BITS_PER_WORD == 32
uint32 vip, vsp, vbp;
__asm {
Label:
mov [vbp], ebp;
mov [vsp], esp;
mov eax, [Label];
mov [vip], eax;
}
regs->ip = vip;
regs->sp = vsp;
regs->bp = vbp;
#else
CONTEXT context;
RtlCaptureContext(&context);
regs->ip = context.Rip;
regs->sp = context.Rsp;
regs->bp = context.Rbp;
#endif
memcpy(buffer, (void *)p, len);
return true;
}
#elif defined(__linux__) && (defined(__x86_64__) || defined(__i386__))
#include <unistd.h>
#include <ucontext.h>
#include <sys/mman.h>
static bool
GetStack(uint64 *stack, uint64 *stack_len, CrashRegisters *regs, char *buffer, size_t size)
{
/* 256 is a fudge factor to account for the rest of GetStack's frame. */
char dummy;
uint64 p = uint64(&dummy) - 256;
uint64 pgsz = getpagesize();
uint64 len = stack_snapshot_max_size;
p &= ~(pgsz - 1);
/* Try to figure out how big the stack is. */
while (len > 0) {
if (mlock((const void *)p, len) == 0) {
munlock((const void *)p, len);
break;
}
len -= pgsz;
}
if (len > size)
len = size;
*stack = p;
*stack_len = len;
/* Get the register state. */
ucontext_t context;
if (getcontext(&context) != 0)
return false;
#if JS_BITS_PER_WORD == 64
regs->sp = (uint64)context.uc_mcontext.gregs[REG_RSP];
regs->bp = (uint64)context.uc_mcontext.gregs[REG_RBP];
regs->ip = (uint64)context.uc_mcontext.gregs[REG_RIP];
#elif JS_BITS_PER_WORD == 32
regs->sp = (uint64)context.uc_mcontext.gregs[REG_ESP];
regs->bp = (uint64)context.uc_mcontext.gregs[REG_EBP];
regs->ip = (uint64)context.uc_mcontext.gregs[REG_EIP];
#endif
memcpy(buffer, (void *)p, len);
return true;
}
#else
static bool
GetStack(uint64 *stack, uint64 *stack_len, CrashRegisters *regs, char *buffer, size_t size)
{
return false;
}
#endif
class Stack : private CrashStack
{
public:
Stack(uint64 id);
bool snapshot();
};
Stack::Stack(uint64 id)
: CrashStack(id)
{
}
bool
Stack::snapshot()
{
snaptime = time(NULL);
return GetStack(&stack_base, &stack_len, &regs, stack, sizeof(stack));
}
class Ring : private CrashRing
{
public:
Ring(uint64 id);
void push(uint64 tag, void *data, size_t size);
private:
size_t bufferSize() { return crash_buffer_size; }
void copyBytes(void *data, size_t size);
};
Ring::Ring(uint64 id)
: CrashRing(id)
{
}
void
Ring::push(uint64 tag, void *data, size_t size)
{
uint64 t = time(NULL);
copyBytes(&tag, sizeof(uint64));
copyBytes(&t, sizeof(uint64));
copyBytes(data, size);
uint64 mysize = size;
copyBytes(&mysize, sizeof(uint64));
}
void
Ring::copyBytes(void *data, size_t size)
{
if (size >= bufferSize())
size = bufferSize();
if (offset + size > bufferSize()) {
size_t first = bufferSize() - offset;
size_t second = size - first;
memcpy(&buffer[offset], data, first);
memcpy(buffer, (char *)data + first, second);
offset = second;
} else {
memcpy(&buffer[offset], data, size);
offset += size;
}
}
static bool gInitialized;
static Stack gGCStack(JS_CRASH_STACK_GC);
static Stack gErrorStack(JS_CRASH_STACK_ERROR);
static Ring gRingBuffer(JS_CRASH_RING);
} /* namespace crash */
} /* namespace js */
using namespace js;
using namespace js::crash;
JS_FRIEND_API(void)
js_SnapshotGCStack()
{
if (gInitialized)
gGCStack.snapshot();
}
JS_FRIEND_API(void)
js_SnapshotErrorStack()
{
if (gInitialized)
gErrorStack.snapshot();
}
JS_FRIEND_API(void)
js_SaveCrashData(uint64 tag, void *ptr, size_t size)
{
if (gInitialized)
gRingBuffer.push(tag, ptr, size);
}
JS_PUBLIC_API(void)
JS_EnumerateDiagnosticMemoryRegions(JSEnumerateDiagnosticMemoryCallback callback)
{
#if 1
if (!gInitialized) {
gInitialized = true;
(*callback)(&gGCStack, sizeof(gGCStack));
(*callback)(&gErrorStack, sizeof(gErrorStack));
(*callback)(&gRingBuffer, sizeof(gRingBuffer));
}
#endif
}

59
js/src/jscrashreport.h Normal file
Просмотреть файл

@ -0,0 +1,59 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=4 sw=4 et tw=99:
*
* ***** 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 SpiderMonkey JavaScript 1.9 code, released
* May 28, 2008.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of 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 ***** */
#ifndef jscrashreport_h___
#define jscrashreport_h___
#include "jstypes.h"
JS_BEGIN_EXTERN_C
JS_FRIEND_API(void)
js_SnapshotGCStack();
JS_FRIEND_API(void)
js_SnapshotErrorStack();
JS_FRIEND_API(void)
js_SaveCrashData(uint64 tag, void *ptr, size_t size);
JS_END_EXTERN_C
#endif /* jscrashreport_h___ */

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

@ -60,6 +60,8 @@
#include "jsapi.h"
#include "jsatom.h"
#include "jscompartment.h"
#include "jscrashreport.h"
#include "jscrashformat.h"
#include "jscntxt.h"
#include "jsversion.h"
#include "jsdbgapi.h"
@ -239,9 +241,7 @@ Arena::finalize(JSContext *cx)
if (!newFreeSpanStart)
newFreeSpanStart = thing;
t->finalize(cx);
#ifdef DEBUG
memset(t, JS_FREE_PATTERN, sizeof(T));
#endif
}
}
}
@ -2662,6 +2662,12 @@ GCCycle(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind GCTIMER_P
(*c)->setGCLastBytes((*c)->gcBytes, gckind);
}
struct GCCrashData
{
int isRegen;
int isCompartment;
};
void
js_GC(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind)
{
@ -2683,6 +2689,11 @@ js_GC(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind)
RecordNativeStackTopForGC(cx);
GCCrashData crashData;
crashData.isRegen = rt->shapeGen & SHAPE_OVERFLOW_BIT;
crashData.isCompartment = !!comp;
js_SaveCrashData(crash::JS_CRASH_TAG_GC, &crashData, sizeof(crashData));
GCTIMER_BEGIN(rt, comp);
do {
@ -2721,6 +2732,8 @@ js_GC(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind)
rt->gcChunkAllocationSinceLastGC = false;
GCTIMER_END(gckind == GC_LAST_CONTEXT);
js_SnapshotGCStack();
}
namespace js {

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

@ -115,6 +115,12 @@ Mark(JSTracer *trc, T *thing)
JS_ASSERT(thing->arenaHeader()->compartment);
JS_ASSERT(thing->arenaHeader()->compartment->rt == rt);
if (rt->gcCheckCompartment && thing->compartment() != rt->gcCheckCompartment &&
thing->compartment() != rt->atomsCompartment)
{
JS_Assert("compartment mismatch in GC", __FILE__, __LINE__);
}
/*
* Don't mark things outside a compartment if we are in a per-compartment
* GC.
@ -158,6 +164,16 @@ MarkObject(JSTracer *trc, JSObject &obj, const char *name)
Mark(trc, &obj);
}
void
MarkCrossCompartmentObject(JSTracer *trc, JSObject &obj, const char *name)
{
JSRuntime *rt = trc->context->runtime;
if (rt->gcCurrentCompartment && rt->gcCurrentCompartment != obj.compartment())
return;
MarkObject(trc, obj, name);
}
void
MarkObjectWithPrinter(JSTracer *trc, JSObject &obj, JSTraceNamePrinter printer,
const void *arg, size_t index)
@ -351,6 +367,22 @@ MarkValue(JSTracer *trc, const js::Value &v, const char *name)
MarkValueRaw(trc, v);
}
void
MarkCrossCompartmentValue(JSTracer *trc, const js::Value &v, const char *name)
{
if (v.isMarkable()) {
js::gc::Cell *cell = (js::gc::Cell *)v.toGCThing();
unsigned kind = v.gcKind();
if (kind == JSTRACE_STRING && ((JSString *)cell)->isStaticAtom())
return;
JSRuntime *rt = trc->context->runtime;
if (rt->gcCurrentCompartment && cell->compartment() != rt->gcCurrentCompartment)
return;
MarkValue(trc, v, name);
}
}
void
MarkValueRange(JSTracer *trc, Value *beg, Value *end, const char *name)
{
@ -748,6 +780,9 @@ MarkChildren(JSTracer *trc, JSXML *xml)
void
GCMarker::drainMarkStack()
{
JSRuntime *rt = context->runtime;
rt->gcCheckCompartment = rt->gcCurrentCompartment;
while (!isMarkStackEmpty()) {
while (!ropeStack.isEmpty())
ScanRope(this, ropeStack.pop());
@ -772,6 +807,8 @@ GCMarker::drainMarkStack()
markDelayedChildren();
}
}
rt->gcCheckCompartment = NULL;
}
} /* namespace js */

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

@ -62,6 +62,13 @@ MarkString(JSTracer *trc, JSString *str, const char *name);
void
MarkObject(JSTracer *trc, JSObject &obj, const char *name);
/*
* Mark an object that may be in a different compartment from the compartment
* being GC'd. (Although it won't be marked if it's in the wrong compartment.)
*/
void
MarkCrossCompartmentObject(JSTracer *trc, JSObject &obj, const char *name);
void
MarkObjectWithPrinter(JSTracer *trc, JSObject &obj, JSTraceNamePrinter printer,
const void *arg, size_t index);
@ -102,6 +109,13 @@ MarkValueRaw(JSTracer *trc, const js::Value &v);
void
MarkValue(JSTracer *trc, const js::Value &v, const char *name);
/*
* Mark a value that may be in a different compartment from the compartment
* being GC'd. (Although it won't be marked if it's in the wrong compartment.)
*/
void
MarkCrossCompartmentValue(JSTracer *trc, const js::Value &v, const char *name);
void
MarkValueRange(JSTracer *trc, Value *beg, Value *end, const char *name);

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

@ -980,11 +980,11 @@ static void
proxy_TraceObject(JSTracer *trc, JSObject *obj)
{
obj->getProxyHandler()->trace(trc, obj);
MarkValue(trc, obj->getProxyPrivate(), "private");
MarkValue(trc, obj->getProxyExtra(), "extra");
MarkCrossCompartmentValue(trc, obj->getProxyPrivate(), "private");
MarkCrossCompartmentValue(trc, obj->getProxyExtra(), "extra");
if (obj->isFunctionProxy()) {
MarkValue(trc, GetCall(obj), "call");
MarkValue(trc, GetConstruct(obj), "construct");
MarkCrossCompartmentValue(trc, GetCall(obj), "call");
MarkCrossCompartmentValue(trc, GetConstruct(obj), "construct");
}
}
@ -992,8 +992,8 @@ static void
proxy_TraceFunction(JSTracer *trc, JSObject *obj)
{
proxy_TraceObject(trc, obj);
MarkValue(trc, GetCall(obj), "call");
MarkValue(trc, GetConstruct(obj), "construct");
MarkCrossCompartmentValue(trc, GetCall(obj), "call");
MarkCrossCompartmentValue(trc, GetConstruct(obj), "construct");
}
static JSBool

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

@ -45,6 +45,7 @@
#define jsutil_h___
#include "jstypes.h"
#include "jscrashreport.h"
#include "mozilla/Util.h"
#include <stdlib.h>
#include <string.h>
@ -59,6 +60,8 @@ JS_BEGIN_EXTERN_C
} \
JS_END_MACRO
#define JS_FREE_PATTERN 0xDA
#ifdef DEBUG
#define JS_ASSERT(expr) \
@ -80,8 +83,6 @@ JS_BEGIN_EXTERN_C
# define JS_THREADSAFE_ASSERT(expr) ((void) 0)
# endif
#define JS_FREE_PATTERN 0xDA
#else
#define JS_ASSERT(expr) ((void) 0)
@ -220,6 +221,12 @@ extern JS_PUBLIC_DATA(JSUint32) OOM_counter; /* data race, who cares. */
#define JS_OOM_POSSIBLY_FAIL() do {} while(0)
#endif
static JS_INLINE void *js_record_oom(void *p) {
if (!p)
js_SnapshotErrorStack();
return p;
}
/*
* SpiderMonkey code should not be calling these allocation functions directly.
* Instead, all calls should go through JSRuntime, JSContext or OffTheBooks.
@ -227,17 +234,17 @@ extern JS_PUBLIC_DATA(JSUint32) OOM_counter; /* data race, who cares. */
*/
static JS_INLINE void* js_malloc(size_t bytes) {
JS_OOM_POSSIBLY_FAIL();
return malloc(bytes);
return js_record_oom(malloc(bytes));
}
static JS_INLINE void* js_calloc(size_t bytes) {
JS_OOM_POSSIBLY_FAIL();
return calloc(bytes, 1);
return js_record_oom(calloc(bytes, 1));
}
static JS_INLINE void* js_realloc(void* p, size_t bytes) {
JS_OOM_POSSIBLY_FAIL();
return realloc(p, bytes);
return js_record_oom(realloc(p, bytes));
}
static JS_INLINE void js_free(void* p) {

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

@ -768,4 +768,10 @@ JSCrossCompartmentWrapper::defaultValue(JSContext *cx, JSObject *wrapper, JSType
return call.origin->wrap(cx, vp);
}
void
JSCrossCompartmentWrapper::trace(JSTracer *trc, JSObject *wrapper)
{
MarkCrossCompartmentObject(trc, *wrappedObject(wrapper), "wrappedObject");
}
JSCrossCompartmentWrapper JSCrossCompartmentWrapper::singleton(0u);

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

@ -153,6 +153,8 @@ class JS_FRIEND_API(JSCrossCompartmentWrapper) : public JSWrapper {
virtual JSString *fun_toString(JSContext *cx, JSObject *wrapper, uintN indent);
virtual bool defaultValue(JSContext *cx, JSObject *wrapper, JSType hint, js::Value *vp);
virtual void trace(JSTracer *trc, JSObject *wrapper);
static JSCrossCompartmentWrapper singleton;
};

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

@ -876,7 +876,7 @@ customMethodCalls = {
'thisType': 'nsGenericElement'
},
'nsIDOMElement_GetTagName': {
'thisType': 'nsINode',
'thisType': 'nsGenericElement',
'code': 'nsString result = self->NodeName();',
'canFail': False
},

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

@ -49,6 +49,10 @@
#include "mozilla/FunctionTimer.h"
#include "prsystem.h"
#ifdef MOZ_CRASHREPORTER
#include "nsExceptionHandler.h"
#endif
using namespace mozilla;
/***************************************************************************/
@ -1667,6 +1671,14 @@ NS_IMPL_THREADSAFE_ISUPPORTS1(
, nsIMemoryMultiReporter
)
#ifdef MOZ_CRASHREPORTER
static JSBool
DiagnosticMemoryCallback(void *ptr, size_t size)
{
return CrashReporter::RegisterAppMemory(ptr, size) == NS_OK;
}
#endif
XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect)
: mXPConnect(aXPConnect),
mJSRuntime(nsnull),
@ -1724,6 +1736,9 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect)
JS_SetWrapObjectCallbacks(mJSRuntime,
xpc::WrapperFactory::Rewrap,
xpc::WrapperFactory::PrepareForWrapping);
#ifdef MOZ_CRASHREPORTER
JS_EnumerateDiagnosticMemoryRegions(DiagnosticMemoryCallback);
#endif
mWatchdogWakeup = JS_NEW_CONDVAR(mJSRuntime->gcLock);
if (!mWatchdogWakeup)
NS_RUNTIMEABORT("JS_NEW_CONDVAR failed.");

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

@ -6629,7 +6629,7 @@ nsFrame::GetParentStyleContextFrame(nsPresContext* aPresContext,
* is needed because the split inline's style context is the parent of the
* anonymous block's style context.
*
* If aFrame is not ananonymous block, null is returned.
* If aFrame is not an anonymous block, null is returned.
*/
static nsIFrame*
GetIBSpecialSiblingForAnonymousBlock(nsIFrame* aFrame)

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

@ -47,6 +47,7 @@
# include <windows.h> // for DebugBreak
#elif defined(XP_UNIX)
# include <unistd.h> // for _exit
# include <signal.h>
#endif
#if defined(XP_WIN) || defined(XP_OS2)
@ -72,19 +73,39 @@ mozalloc_abort(const char* const msg)
fputs(msg, stderr);
fputs("\n", stderr);
#if defined(XP_UNIX) && !defined(XP_MACOSX)
abort();
#elif defined(_MSC_VER)
#if defined(_MSC_VER)
__debugbreak();
#elif defined(XP_WIN)
DebugBreak();
#endif
// abort() doesn't trigger breakpad on Mac, "fall through" to the
// fail-safe code
// Still haven't aborted? Try dereferencing null.
// On *NIX platforms the prefered way to abort is by touching bad memory,
// since this generates a stack trace inside our own code (avoiding
// problems with starting the trace inside libc, where we might not have
// symbols and can get lost).
TouchBadMemory();
// If we haven't aborted yet, we can try to raise SIGABRT which might work
// on some *NIXs, but not OS X (it doesn't trigger breakpad there).
// Note that we don't call abort(), since raise is likelier to give us
// useful stack data, and also since abort() is redirected to call this
// function (see below).
#if defined(XP_UNIX) && !defined(XP_MACOSX)
raise(SIGABRT);
#endif
// Still haven't aborted? Try _exit().
_exit(127);
}
#if defined(XP_UNIX)
// Define abort() here, so that it is used instead of the system abort(). This
// lets us control the behavior when aborting, in order to get better results
// on *NIX platfrorms. See mozalloc_abort for details.
void abort(void)
{
mozalloc_abort("Redirecting call to abort() to mozalloc_abort\n");
}
#endif

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

@ -384,6 +384,10 @@ pref("content.sink.perf_parse_time", 50000000);
pref("javascript.options.mem.high_water_mark", 32);
// Disable the JS engine's gc on memory pressure, since we do one in the mobile
// browser (bug 669346).
pref("javascript.options.gc_on_memory_pressure", false);
pref("dom.max_chrome_script_run_time", 0); // disable slow script dialog for chrome
pref("dom.max_script_run_time", 20);

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

@ -69,6 +69,7 @@ XPCOMUtils.defineLazyGetter(this, "CommonUI", function() {
[
["FullScreenVideo"],
["WebappsUI"],
["BadgeHandlers"],
["ContextHelper"],
["SelectionHelper"],

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

@ -1038,6 +1038,21 @@ var BrowserUI = {
return this._domWindowClose(browser);
break;
case "DOMLinkAdded":
// checks for an icon to use for a web app
// priority is : icon < apple-touch-icon
let rel = json.rel.toLowerCase().split(" ");
if ((rel.indexOf("icon") != -1) && !browser.appIcon) {
// We should also use the sizes attribute if available
// see http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#rel-icon
browser.appIcon = json.href;
}
else if (rel.indexOf("apple-touch-icon") != -1) {
// XXX should we support apple-touch-icon-precomposed ?
// see http://developer.apple.com/safari/library/documentation/appleapplications/reference/safariwebcontent/configuringwebapplications/configuringwebapplications.html
browser.appIcon = json.href;
}
// Handle favicon changes
if (Browser.selectedBrowser == browser)
this._updateIcon(Browser.selectedBrowser.mIconURL);
break;
@ -1238,7 +1253,8 @@ var BrowserUI = {
this.activePanel = RemoteTabsList;
break;
case "cmd_quit":
GlobalOverlay.goQuitApplication();
// Only close one window
this._closeOrQuit();
break;
case "cmd_close":
this._closeOrQuit();

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

@ -378,13 +378,14 @@ var Browser = {
messageManager.addMessageListener("Browser:CertException", this);
messageManager.addMessageListener("Browser:BlockedSite", this);
// broadcast a UIReady message so add-ons know we are finished with startup
// Broadcast a UIReady message so add-ons know we are finished with startup
let event = document.createEvent("Events");
event.initEvent("UIReady", true, false);
window.dispatchEvent(event);
// if we have an opener this was not the first window opened and will not
// If we have an opener this was not the first window opened and will not
// receive an initial resize event. instead we fire the resize handler manually
// Bug 610834
if (window.opener)
resizeHandler({ target: window });
},
@ -941,7 +942,7 @@ var Browser = {
function visibility(aSidebarRect, aVisibleRect) {
let width = aSidebarRect.width;
aSidebarRect.restrictTo(aVisibleRect);
return (aSidebarRect.width ? aSidebarRect.width / width : 0);
return (width ? aSidebarRect.width / width : 0);
}
if (!dx) dx = 0;
@ -1492,6 +1493,7 @@ Browser.WebProgress.prototype = {
tab.hostChanged = true;
tab.browser.lastLocation = location;
tab.browser.userTypedValue = "";
tab.browser.appIcon = null;
#ifdef MOZ_CRASH_REPORTER
if (CrashReporter.enabled)
@ -1576,6 +1578,8 @@ Browser.WebProgress.prototype = {
};
const OPEN_APPTAB = 100; // Hack until we get a real API
function nsBrowserAccess() { }
nsBrowserAccess.prototype = {
@ -1618,13 +1622,31 @@ nsBrowserAccess.prototype = {
tab.closeOnExit = true;
browser = tab.browser;
BrowserUI.hidePanel();
} else if (aWhere == OPEN_APPTAB) {
Browser.tabs.forEach(function(aTab) {
if ("appURI" in aTab.browser && aTab.browser.appURI.spec == aURI.spec) {
Browser.selectedTab = aTab;
browser = aTab.browser;
}
});
if (!browser) {
// Make a new tab to hold the app
let tab = Browser.addTab("about:blank", true, null, { getAttention: true });
browser = tab.browser;
browser.appURI = aURI;
} else {
// Just use the existing browser, but return null to keep the system from trying to load the URI again
browser = null;
}
BrowserUI.hidePanel();
} else { // OPEN_CURRENTWINDOW and illegal values
browser = Browser.selectedBrowser;
}
try {
let referrer;
if (aURI) {
if (aURI && browser) {
if (aOpener) {
location = aOpener.location;
referrer = Services.io.newURI(location, null, null);
@ -2518,8 +2540,16 @@ var ContentCrashObserver = {
var MemoryObserver = {
observe: function mo_observe(aSubject, aTopic, aData) {
function gc() {
window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils).garbageCollect();
Cu.forceGC();
};
if (aData == "heap-minimize") {
// do non-destructive stuff here.
// The JS engine would normally GC on this notification, but since we
// disabled that in favor of this method (bug 669346), we should gc here.
gc();
return;
}
@ -2530,9 +2560,9 @@ var MemoryObserver = {
tab.resurrect();
}
window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils).garbageCollect();
Cu.forceGC();
// gc *after* throwing out the tabs so we can reclaim that memory.
gc();
// Bug 637582 - The low memory condition throws out some stuff that we still
// need, re-selecting the active tab gets us back to where we need to be.
let sTab = Browser.selectedTab;

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

@ -68,10 +68,9 @@
title="&brandShortName;"
#ifdef MOZ_PLATFORM_MAEMO
sizemode="fullscreen"
#else
#endif
width="480"
height="800"
#endif
onkeypress="onDebugKeyPress(event);"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml">
@ -349,6 +348,7 @@
onclick="PageActions.clearPagePermissions(event);"/>
<pageaction id="pageaction-search" title="&pageactions.search.addNew;"/>
<pageaction id="pageaction-charset" title="&pageactions.charEncoding;" onclick="CharsetMenu.show();"/>
<pageaction id="pageaction-webapps-install" title="&pageactions.webapps.install;" onclick="WebappsUI.show();"/>
</hbox>
</arrowbox>

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

@ -174,6 +174,7 @@ var PageActions = {
#endif
this.register("pageaction-share", this.updateShare, this);
this.register("pageaction-search", BrowserSearch.updatePageSearchEngines, BrowserSearch);
this.register("pageaction-webapps-install", WebappsUI.updateWebappsInstall, WebappsUI);
},
handleEvent: function handleEvent(aEvent) {
@ -1658,3 +1659,128 @@ var CharsetMenu = {
}
};
var WebappsUI = {
_dialog: null,
_manifest: null,
checkBox: function(aEvent) {
let elem = aEvent.originalTarget;
let perm = elem.getAttribute("perm");
if (this._manifest.capabilities && this._manifest.capabilities.indexOf(perm) != -1) {
if (elem.checked) {
elem.classList.remove("webapps-noperm");
elem.classList.add("webapps-perm");
} else {
elem.classList.remove("webapps-perm");
elem.classList.add("webapps-noperm");
}
}
},
show: function show(aManifest) {
if (!aManifest) {
// Try every way to get an icon
let browser = Browser.selectedBrowser;
let icon = browser.appIcon;
if (!icon)
icon = browser.mIconURL;
if (!icon)
icon = gFaviconService.getFaviconImageForPage(browser.currentURI).spec;
// Create a simple manifest
aManifest = {
uri: browser.currentURI.spec,
name: browser.contentTitle,
icon: icon
};
}
this._manifest = aManifest;
this._dialog = importDialog(window, "chrome://browser/content/webapps.xul", null);
if (aManifest.name)
document.getElementById("webapps-title").value = aManifest.name;
if (aManifest.icon)
document.getElementById("webapps-icon").src = aManifest.icon;
let uri = Services.io.newURI(aManifest.uri, null, null);
let perms = [["offline", "offline-app"], ["geoloc", "geo"], ["notifications", "desktop-notifications"]];
perms.forEach(function(tuple) {
let elem = document.getElementById("webapps-" + tuple[0] + "-checkbox");
let currentPerm = Services.perms.testExactPermission(uri, tuple[1]);
if ((aManifest.capabilities && (aManifest.capabilities.indexOf(tuple[1]) != -1)) || (currentPerm == Ci.nsIPermissionManager.ALLOW_ACTION))
elem.checked = true;
else
elem.checked = (currentPerm == Ci.nsIPermissionManager.ALLOW_ACTION);
elem.classList.remove("webapps-noperm");
elem.classList.add("webapps-perm");
});
BrowserUI.pushPopup(this, this._dialog);
// Force a modal dialog
this._dialog.waitForClose();
},
hide: function hide() {
this._dialog.close();
this._dialog = null;
BrowserUI.popPopup(this);
},
_updatePermission: function updatePermission(aId, aPerm) {
try {
let uri = Services.io.newURI(this._manifest.uri, null, null);
Services.perms.add(uri, aPerm, document.getElementById(aId).checked ? Ci.nsIPermissionManager.ALLOW_ACTION : Ci.nsIPermissionManager.DENY_ACTION);
} catch(e) {
Cu.reportError(e);
}
},
launch: function launch() {
let title = document.getElementById("webapps-title").value;
if (!title)
return;
this._updatePermission("webapps-offline-checkbox", "offline-app");
this._updatePermission("webapps-geoloc-checkbox", "geo");
this._updatePermission("webapps-notifications-checkbox", "desktop-notification");
this.hide();
this.install(this._manifest.uri, title, this._manifest.icon);
},
updateWebappsInstall: function updateWebappsInstall(aNode) {
return !document.getElementById("main-window").hasAttribute("webapp");
},
install: function(aURI, aTitle, aIcon) {
const kIconSize = 64;
let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
canvas.setAttribute("style", "display: none");
let self = this;
let image = new Image();
image.onload = function() {
canvas.width = canvas.height = kIconSize; // clears the canvas
let ctx = canvas.getContext("2d");
ctx.drawImage(image, 0, 0, kIconSize, kIconSize);
let data = canvas.toDataURL("image/png", "");
canvas = null;
try {
let webapp = Cc["@mozilla.org/webapps/support;1"].getService(Ci.nsIWebappsSupport);
webapp.installApplication(aTitle, aURI, aIcon, data);
} catch(e) {
Cu.reportError(e);
}
}
image.onerror = function() {
// can't load the icon (bad URI) : fallback to the default one from chrome
self.install(aURI, aTitle, "chrome://browser/skin/images/favicon-default-30.png");
}
image.src = aIcon;
}
};

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

@ -0,0 +1,94 @@
<?xml version="1.0"?>
<!-- ***** 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 Mobile Browser.
-
- The Initial Developer of the Original Code is
- Mozilla Corporation.
- Portions created by the Initial Developer are Copyright (C) 2008
- the Initial Developer. All Rights Reserved.
-
- Contributor(s):
- Fabrice Desré <fabrice@mozilla.com>
-
- 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 LGPL or the GPL. 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 ***** -->
<!DOCTYPE dialog [
<!ENTITY % promptDTD SYSTEM "chrome://browser/locale/prompt.dtd">
%promptDTD;
<!ENTITY % webappsDTD SYSTEM "chrome://browser/locale/webapps.dtd">
%webappsDTD;
]>
<dialog id="webapp-dialog" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<keyset>
<key keycode="VK_ESCAPE" command="cmd_cancel"/>
<key keycode="VK_RETURN" command="cmd_ok"/>
</keyset>
<commandset>
<command id="cmd_cancel" oncommand="WebappsUI.hide();"/>
<command id="cmd_ok" oncommand="WebappsUI.launch();"/>
</commandset>
<vbox class="prompt-title" id="webapps-title-box">
<hbox align="center">
<image id="webapps-icon"/>
<vbox flex="1">
<textbox id="webapps-title" placeholder="&webapps.title.placeholder;" flex="1"/>
</vbox>
</hbox>
</vbox>
<separator class="prompt-line"/>
<scrollbox class="prompt-message prompt-header" id="webapps-perm-box" orient="vertical" oncommand="WebappsUI.checkBox(event)" flex="1">
<label crop="center" flex="1" value="&webapps.permissions;"/>
<button id="webapps-geoloc-checkbox" perm="geo" type="checkbox" class="button-checkbox webapps-perm" flex="1">
<image class="button-image-icon"/>
<vbox flex="1">
<description class="prompt-checkbox-label" flex="1">&webapps.perm.geolocation;</description>
<description class="prompt-checkbox-label webapps-perm-requested-hint" id="webapps-geoloc-app">&webapps.perm.requested;</description>
</vbox>
</button>
<button id="webapps-offline-checkbox" perm="offline-app" type="checkbox" class="button-checkbox webapps-perm" flex="1">
<image class="button-image-icon"/>
<vbox flex="1">
<description class="prompt-checkbox-label" flex="1">&webapps.perm.offline;</description>
<description class="prompt-checkbox-label webapps-perm-requested-hint" id="webapps-offline-app">&webapps.perm.requested;</description>
</vbox>
</button>
<button id="webapps-notifications-checkbox" perm="desktop-notifications" type="checkbox" class="button-checkbox webapps-perm" flex="1">
<image class="button-image-icon"/>
<vbox flex="1">
<description class="prompt-checkbox-label" flex="1">&webapps.perm.notifications;</description>
<description class="prompt-checkbox-label webapps-perm-requested-hint" id="webapps-notifications-app">&webapps.perm.requested;</description>
</vbox>
</button>
</scrollbox>
<hbox pack="center" class="prompt-buttons">
<button class="prompt-button" command="cmd_ok" label="&ok.label;"/>
<separator/>
<button class="prompt-button" command="cmd_cancel" label="&cancel.label;"/>
</hbox>
</dialog>

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

@ -64,6 +64,7 @@ chrome.jar:
content/prompt/select.xul (content/prompt/select.xul)
content/prompt/prompt.js (content/prompt/prompt.js)
content/share.xul (content/share.xul)
content/webapps.xul (content/webapps.xul)
content/AnimatedZoom.js (content/AnimatedZoom.js)
#ifdef MOZ_SERVICES_SYNC
content/sync.js (content/sync.js)

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

@ -44,12 +44,12 @@ Cu.import("resource://gre/modules/Services.jsm");
function openWindow(aParent, aURL, aTarget, aFeatures, aArgs) {
let argString = null;
if (aArgs) {
if (aArgs && !(aArgs instanceof Ci.nsISupportsArray)) {
argString = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
argString.data = aArgs;
}
return Services.ww.openWindow(aParent, aURL, aTarget, aFeatures, argString);
return Services.ww.openWindow(aParent, aURL, aTarget, aFeatures, argString || aArgs);
}
function resolveURIInternal(aCmdLine, aArgument) {
@ -61,16 +61,14 @@ function resolveURIInternal(aCmdLine, aArgument) {
try {
if (uri.file.exists())
return uri;
}
catch (e) {
} catch (e) {
Cu.reportError(e);
}
try {
let urifixup = Cc["@mozilla.org/docshell/urifixup;1"].getService(Ci.nsIURIFixup);
uri = urifixup.createFixupURI(aArgument, 0);
}
catch (e) {
} catch (e) {
Cu.reportError(e);
}
@ -155,8 +153,7 @@ BrowserCLH.prototype = {
// Stop the normal commandline processing from continuing
aCmdLine.preventDefault = true;
}
}
catch (e) {
} catch (e) {
Cu.reportError(e);
}
return;
@ -165,6 +162,12 @@ BrowserCLH.prototype = {
// Check and remove the alert flag here, but we'll handle it a bit later - see below
let alertFlag = aCmdLine.handleFlagWithParam("alert", false);
// Check and remove the webapp param
let appFlag = aCmdLine.handleFlagWithParam("webapp", false);
let appURI;
if (appFlag)
appURI = resolveURIInternal(aCmdLine, appFlag);
// Keep an array of possible URL arguments
let uris = [];
@ -187,16 +190,17 @@ BrowserCLH.prototype = {
}
// Open the main browser window, if we don't already have one
let win;
let localePickerWin;
let browserWin;
try {
win = Services.wm.getMostRecentWindow("navigator:browser");
localePickerWin = Services.wm.getMostRecentWindow("navigator:localepicker");
if (localePickerWin) {
localePickerWin.focus();
let localeWin = Services.wm.getMostRecentWindow("navigator:localepicker");
if (localeWin) {
localeWin.focus();
aCmdLine.preventDefault = true;
return;
} else if (!win) {
}
browserWin = Services.wm.getMostRecentWindow("navigator:browser");
if (!browserWin) {
// Default to the saved homepage
let defaultURL = getHomePage();
@ -208,30 +212,35 @@ BrowserCLH.prototype = {
// Show the locale selector if we have a new profile
if (needHomepageOverride() == "new profile" && Services.prefs.getBoolPref("browser.firstrun.show.localepicker")) {
win = openWindow(null, "chrome://browser/content/localePicker.xul", "_blank", "chrome,dialog=no,all", defaultURL);
browserWin = openWindow(null, "chrome://browser/content/localePicker.xul", "_blank", "chrome,dialog=no,all", defaultURL);
aCmdLine.preventDefault = true;
return;
}
win = openWindow(null, "chrome://browser/content/browser.xul", "_blank", "chrome,dialog=no,all", defaultURL);
browserWin = openWindow(null, "chrome://browser/content/browser.xul", "_blank", "chrome,dialog=no,all", defaultURL);
}
win.focus();
browserWin.focus();
// Stop the normal commandline processing from continuing. We just opened the main browser window
aCmdLine.preventDefault = true;
} catch (e) { }
} catch (e) {
Cu.reportError(e);
}
// Assumption: All remaining command line arguments have been sent remotely (browser is already running)
// Action: Open any URLs we find into an existing browser window
// First, get a browserDOMWindow object
while (!win.browserDOMWindow)
while (!browserWin.browserDOMWindow)
Services.tm.currentThread.processNextEvent(true);
// Open any URIs into new tabs
for (let i = 0; i < uris.length; i++)
win.browserDOMWindow.openURI(uris[i], null, Ci.nsIBrowserDOMWindow.OPEN_NEWTAB, Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL);
browserWin.browserDOMWindow.openURI(uris[i], null, Ci.nsIBrowserDOMWindow.OPEN_NEWTAB, Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL);
if (appURI)
browserWin.browserDOMWindow.openURI(appURI, null, browserWin.OPEN_APPTAB, Ci.nsIBrowserDOMWindow.OPEN_NEW);
// Handle the notification, if called from it
if (alertFlag) {
@ -243,9 +252,9 @@ BrowserCLH.prototype = {
var updateTimerCallback = updateService.QueryInterface(Ci.nsITimerCallback);
updateTimerCallback.notify(null);
} else if (alertFlag.length >= 9 && alertFlag.substr(0, 9) == "download:") {
showPanelWhenReady(win, "downloads-container");
showPanelWhenReady(browserWin, "downloads-container");
} else if (alertFlag == "addons") {
showPanelWhenReady(win, "addons-container");
showPanelWhenReady(browserWin, "addons-container");
}
}
},

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

@ -75,6 +75,7 @@ EXTRA_COMPONENTS = \
LoginManager.js \
LoginManagerPrompter.js \
BlocklistPrompt.js \
WebappsSupport.js \
$(NULL)
ifdef MOZ_SAFE_BROWSING

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

@ -120,3 +120,7 @@ category app-startup SafeBrowsing service,@mozilla.org/safebrowsing/application;
component {88b3eb21-d072-4e3b-886d-f89d8c49fe59} UpdatePrompt.js
contract @mozilla.org/updates/update-prompt;1 {88b3eb21-d072-4e3b-886d-f89d8c49fe59}
#endif
# webapps
component {cb1107c1-1e15-4f11-99c8-27b9ec221a2a} WebappsSupport.js
contract @mozilla.org/webapps/support;1 {cb1107c1-1e15-4f11-99c8-27b9ec221a2a}

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

@ -0,0 +1,125 @@
/* ***** 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 Mobile Browser.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Fabrice Desré <fabrice@mozilla.com>
* Mark Finkle <mfinkle@mozilla.com>
*
* 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 ***** */
const Cu = Components.utils;
const Cc = Components.classes;
const Ci = Components.interfaces;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
const DB_VERSION = 1;
function WebappsSupport() {
this.init();
}
WebappsSupport.prototype = {
db: null,
init: function() {
let file = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties).get("ProfD", Ci.nsIFile);
file.append("webapps.sqlite");
this.db = Services.storage.openDatabase(file);
let version = this.db.schemaVersion;
if (version == 0) {
this.db.executeSimpleSQL("CREATE TABLE webapps (title TEXT, uri TEXT PRIMARY KEY, icon TEXT)");
this.db.schemaVersion = DB_VERSION;
}
XPCOMUtils.defineLazyGetter(this, "_installQuery", function() {
return this.db.createAsyncStatement("INSERT INTO webapps (title, uri, icon) VALUES(:title, :uri, :icon)");
});
XPCOMUtils.defineLazyGetter(this, "_findQuery", function() {
return this.db.createStatement("SELECT uri FROM webapps where uri = :uri");
});
Services.obs.addObserver(this, "quit-application-granted", false);
},
// entry point
installApplication: function(aTitle, aURI, aIconURI, aIconData) {
let stmt = this._installQuery;
stmt.params.title = aTitle;
stmt.params.uri = aURI;
stmt.params.icon = aIconData;
stmt.executeAsync();
},
isApplicationInstalled: function(aURI) {
let stmt = this._findQuery;
let found = false;
try {
stmt.params.uri = aURI;
found = stmt.executeStep();
} finally {
stmt.reset();
}
return found;
},
// nsIObserver
observe: function(aSubject, aTopic, aData) {
Services.obs.removeObserver(this, "quit-application-granted");
// Finalize the statements that we have used
let stmts = [
"_installQuery",
"_findQuery"
];
for (let i = 0; i < stmts.length; i++) {
// We do not want to create any query we haven't already created, so
// see if it is a getter first.
if (Object.getOwnPropertyDescriptor(this, stmts[i]).value !== undefined) {
this[stmts[i]].finalize();
}
}
this.db.asyncClose();
},
// QI
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebappsSupport]),
// XPCOMUtils factory
classID: Components.ID("{cb1107c1-1e15-4f11-99c8-27b9ec221a2a}")
};
const NSGetFactory = XPCOMUtils.generateNSGetFactory([WebappsSupport]);

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

@ -275,6 +275,7 @@
@BINPATH@/components/xuldoc.xpt
@BINPATH@/components/xultmpl.xpt
@BINPATH@/components/zipwriter.xpt
@BINPATH@/components/webapps.xpt
; JavaScript components
@BINPATH@/components/ConsoleAPI.manifest
@ -330,6 +331,7 @@
@BINPATH@/components/amContentHandler.js
@BINPATH@/components/amWebInstallListener.js
@BINPATH@/components/nsBlocklistService.js
#ifdef MOZ_UPDATER
@BINPATH@/components/nsUpdateService.manifest
@BINPATH@/components/nsUpdateService.js
@ -610,6 +612,7 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DLL_SUFFIX@
#ifdef MOZ_UPDATER
@BINPATH@/components/UpdatePrompt.js
#endif
@BINPATH@/components/WebappsSupport.js
@BINPATH@/components/XPIDialogService.js
@BINPATH@/components/browsercomps.xpt
@BINPATH@/extensions/feedback@mobile.mozilla.org.xpi

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

@ -111,5 +111,6 @@
<!ENTITY pageactions.findInPage "Find In Page">
<!ENTITY pageactions.search.addNew "Add Search Engine">
<!ENTITY pageactions.charEncoding "Character Encoding">
<!ENTITY pageactions.webapps.install "Install as App">
<!ENTITY appMenu.siteOptions "Site Options">

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

@ -0,0 +1,6 @@
<!ENTITY webapps.title.placeholder "Enter a title">
<!ENTITY webapps.permissions "Allow access:">
<!ENTITY webapps.perm.geolocation "Location-aware browsing">
<!ENTITY webapps.perm.offline "Offline data storage">
<!ENTITY webapps.perm.notifications "Desktop notifications">
<!ENTITY webapps.perm.requested "requested">

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

@ -16,6 +16,7 @@
locale/@AB_CD@/browser/sync.dtd (%chrome/sync.dtd)
locale/@AB_CD@/browser/sync.properties (%chrome/sync.properties)
locale/@AB_CD@/browser/prompt.dtd (%chrome/prompt.dtd)
locale/@AB_CD@/browser/webapps.dtd (%chrome/webapps.dtd)
locale/@AB_CD@/browser/feedback.dtd (%chrome/feedback.dtd)
locale/@AB_CD@/browser/phishing.dtd (%chrome/phishing.dtd)
locale/@AB_CD@/browser/bookmarks.json (bookmarks.json)

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

@ -1329,6 +1329,25 @@ setting {
z-index: 500;
}
/* openwebapps capabilities ------------------------------------------------------------ */
.webapps-noperm description.webapps-perm-requested-hint {
display: block;
}
.webapps-perm description.webapps-perm-requested-hint {
display: none;
}
#webapps-icon {
width: 48px;
height: 48px;
margin: @margin_normal@;
}
#webapps-title {
-moz-margin-end: @margin_normal@;
}
/* Android menu ------------------------------------------------------------ */
#appmenu {
background: rgba(255,255,255,0.95);

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

@ -1311,6 +1311,25 @@ setting {
z-index: 500;
}
/* openwebapps capabilities ------------------------------------------------------------ */
.webapps-noperm description.webapps-perm-requested-hint {
display: block;
}
.webapps-perm description.webapps-perm-requested-hint {
display: none;
}
#webapps-icon {
width: 32px;
height: 32px;
margin: @margin_normal@;
}
#webapps-title {
-moz-margin-end: @margin_normal@;
}
/* Android menu ------------------------------------------------------------ */
#appmenu {
background: @color_background_default@;

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

@ -287,12 +287,13 @@ toolbarbutton[open="true"] {
list-style-image: url("chrome://browser/skin/images/check-selected-hdpi.png");
}
.button-checkbox > .button-box,
.button-checkbox:hover:active > .button-box,
.button-checkbox[checked="true"] > .button-box {
padding-top: @padding_tiny@;
padding-bottom: @padding_xsmall@;
-moz-padding-start: @margin_small@;
-moz-padding-end: @margin_small@;
-moz-padding-start: @padding_small@;
-moz-padding-end: @padding_small@;
}
/* radio buttons ----------------------------------------------------------- */

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

@ -158,30 +158,30 @@ public:
NS_DECL_ISUPPORTS
NS_IMETHOD GetProcess(char **process)
NS_IMETHOD GetProcess(nsACString &process)
{
*process = strdup("");
process.Truncate();
return NS_OK;
}
NS_IMETHOD GetPath(char **memoryPath)
NS_IMETHOD GetPath(nsACString &path)
{
if (mType == ChromeUsedRaw) {
*memoryPath = strdup("explicit/images/chrome/used/raw");
path.AssignLiteral("explicit/images/chrome/used/raw");
} else if (mType == ChromeUsedUncompressed) {
*memoryPath = strdup("explicit/images/chrome/used/uncompressed");
path.AssignLiteral("explicit/images/chrome/used/uncompressed");
} else if (mType == ChromeUnusedRaw) {
*memoryPath = strdup("explicit/images/chrome/unused/raw");
path.AssignLiteral("explicit/images/chrome/unused/raw");
} else if (mType == ChromeUnusedUncompressed) {
*memoryPath = strdup("explicit/images/chrome/unused/uncompressed");
path.AssignLiteral("explicit/images/chrome/unused/uncompressed");
} else if (mType == ContentUsedRaw) {
*memoryPath = strdup("explicit/images/content/used/raw");
path.AssignLiteral("explicit/images/content/used/raw");
} else if (mType == ContentUsedUncompressed) {
*memoryPath = strdup("explicit/images/content/used/uncompressed");
path.AssignLiteral("explicit/images/content/used/uncompressed");
} else if (mType == ContentUnusedRaw) {
*memoryPath = strdup("explicit/images/content/unused/raw");
path.AssignLiteral("explicit/images/content/unused/raw");
} else if (mType == ContentUnusedUncompressed) {
*memoryPath = strdup("explicit/images/content/unused/uncompressed");
path.AssignLiteral("explicit/images/content/unused/uncompressed");
}
return NS_OK;
}
@ -249,24 +249,24 @@ public:
return NS_OK;
}
NS_IMETHOD GetDescription(char **desc)
NS_IMETHOD GetDescription(nsACString &desc)
{
if (mType == ChromeUsedRaw) {
*desc = strdup("Memory used by in-use chrome images (compressed data).");
desc.AssignLiteral("Memory used by in-use chrome images (compressed data).");
} else if (mType == ChromeUsedUncompressed) {
*desc = strdup("Memory used by in-use chrome images (uncompressed data).");
desc.AssignLiteral("Memory used by in-use chrome images (uncompressed data).");
} else if (mType == ChromeUnusedRaw) {
*desc = strdup("Memory used by not in-use chrome images (compressed data).");
desc.AssignLiteral("Memory used by not in-use chrome images (compressed data).");
} else if (mType == ChromeUnusedUncompressed) {
*desc = strdup("Memory used by not in-use chrome images (uncompressed data).");
desc.AssignLiteral("Memory used by not in-use chrome images (uncompressed data).");
} else if (mType == ContentUsedRaw) {
*desc = strdup("Memory used by in-use content images (compressed data).");
desc.AssignLiteral("Memory used by in-use content images (compressed data).");
} else if (mType == ContentUsedUncompressed) {
*desc = strdup("Memory used by in-use content images (uncompressed data).");
desc.AssignLiteral("Memory used by in-use content images (uncompressed data).");
} else if (mType == ContentUnusedRaw) {
*desc = strdup("Memory used by not in-use content images (compressed data).");
desc.AssignLiteral("Memory used by not in-use content images (compressed data).");
} else if (mType == ContentUnusedUncompressed) {
*desc = strdup("Memory used by not in-use content images (uncompressed data).");
desc.AssignLiteral("Memory used by not in-use content images (uncompressed data).");
}
return NS_OK;
}

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

@ -628,6 +628,7 @@ pref("javascript.options.mem.high_water_mark", 128);
pref("javascript.options.mem.max", -1);
pref("javascript.options.mem.gc_per_compartment", true);
pref("javascript.options.mem.log", false);
pref("javascript.options.gc_on_memory_pressure", true);
// advanced prefs
pref("advanced.mailftp", false);

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

@ -649,8 +649,12 @@ nsHttpChannel::CallOnStartRequest()
mTracingEnabled = PR_FALSE;
if (mResponseHead && mResponseHead->ContentType().IsEmpty()) {
NS_ASSERTION(mConnectionInfo, "Should have connection info here");
if (!mContentTypeHint.IsEmpty())
mResponseHead->SetContentType(mContentTypeHint);
else if (mResponseHead->Version() == NS_HTTP_VERSION_0_9 &&
mConnectionInfo->Port() != mConnectionInfo->DefaultPort())
mResponseHead->SetContentType(NS_LITERAL_CSTRING(TEXT_PLAIN));
else {
// Uh-oh. We had better find out what type we are!

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

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
@ -568,6 +568,12 @@ WebSocketChannel::~WebSocketChannel()
mContext.forget(&forgettableContext);
NS_ProxyRelease(mainThread, forgettableContext, PR_FALSE);
}
if (mLoadGroup) {
nsILoadGroup *forgettableGroup;
mLoadGroup.forget(&forgettableGroup);
NS_ProxyRelease(mainThread, forgettableGroup, PR_FALSE);
}
}
void

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

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
@ -209,7 +209,6 @@ private:
nsCOMPtr<nsIEventTarget> mSocketThread;
nsCOMPtr<nsIHttpChannelInternal> mChannel;
nsCOMPtr<nsIHttpChannel> mHttpChannel;
nsCOMPtr<nsILoadGroup> mLoadGroup;
nsCOMPtr<nsICancelable> mDNSRequest;
nsCOMPtr<nsIAsyncVerifyRedirectCallback> mRedirectCallback;
nsCOMPtr<nsIRandomGenerator> mRandomGenerator;

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

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 ts=4 et tw=80 : */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1

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

@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 ts=4 et tw=80 : */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1

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

@ -0,0 +1,81 @@
do_load_httpd_js();
var httpserver = null;
var simplePath = "/simple";
var normalPath = "/normal";
var httpbody = "<html></html>";
var uri1 = "http://localhost:4444" + simplePath;
var uri2 = "http://localhost:4444" + normalPath;
function make_channel(url) {
var ios = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
return ios.newChannel(url, "", null);
}
var listener_proto = {
QueryInterface: function(iid) {
if (iid.equals(Components.interfaces.nsIStreamListener) ||
iid.equals(Components.interfaces.nsIRequestObserver) ||
iid.equals(Components.interfaces.nsISupports))
return this;
throw Components.results.NS_ERROR_NO_INTERFACE;
},
onStartRequest: function(request, context) {
do_check_eq(request.QueryInterface(Ci.nsIChannel).contentType,
this.contentType);
request.cancel(Cr.NS_BINDING_ABORTED);
},
onDataAvailable: function(request, context, stream, offset, count) {
do_throw("Unexpected onDataAvailable");
},
onStopRequest: function(request, context, status) {
do_check_eq(status, Cr.NS_BINDING_ABORTED);
this.termination_func();
}
};
function listener(contentType, termination_func) {
this.contentType = contentType;
this.termination_func = termination_func;
}
listener.prototype = listener_proto;
function run_test()
{
httpserver = new nsHttpServer();
httpserver.registerPathHandler(simplePath, simpleHandler);
httpserver.registerPathHandler(normalPath, normalHandler);
httpserver.start(4444);
var channel = make_channel(uri1);
channel.asyncOpen(new listener("text/plain", function() {
run_test2();
}), null);
do_test_pending();
}
function run_test2()
{
var channel = make_channel(uri2);
channel.asyncOpen(new listener("text/html", function() {
httpserver.stop(do_test_finished);
}), null);
}
function simpleHandler(metadata, response)
{
response.seizePower();
response.bodyOutputStream.write(httpbody, httpbody.length);
response.finish();
}
function normalHandler(metadata, response)
{
response.bodyOutputStream.write(httpbody, httpbody.length);
response.finish();
}

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

@ -68,6 +68,7 @@ tail =
[test_bug659569.js]
[test_bug660066.js]
[test_bug651185.js]
[test_bug667907.js]
[test_cacheflags.js]
[test_channel_close.js]
[test_compareURIs.js]

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

@ -348,17 +348,15 @@ public:
}
NS_IMETHOD GetProcess(char **process)
NS_IMETHOD GetProcess(nsACString &process)
{
*process = strdup("");
process.Truncate();
return NS_OK;
}
NS_IMETHOD GetPath(char **memoryPath)
NS_IMETHOD GetPath(nsACString &path)
{
nsCString path;
path.AppendLiteral("explicit/storage/sqlite/");
path.AssignLiteral("explicit/storage/sqlite/");
path.Append(mDBConn.getFilename());
if (mType == Cache_Used) {
@ -370,8 +368,6 @@ public:
else if (mType == Stmt_Used) {
path.AppendLiteral("/stmt-used");
}
*memoryPath = ::ToNewCString(path);
return NS_OK;
}
@ -406,17 +402,17 @@ public:
return convertResultCode(rc);
}
NS_IMETHOD GetDescription(char **desc)
NS_IMETHOD GetDescription(nsACString &desc)
{
if (mType == Cache_Used) {
*desc = ::strdup("Memory (approximate) used by all pager caches.");
desc.AssignLiteral("Memory (approximate) used by all pager caches.");
}
else if (mType == Schema_Used) {
*desc = ::strdup("Memory (approximate) used to store the schema "
"for all databases associated with the connection");
desc.AssignLiteral("Memory (approximate) used to store the schema "
"for all databases associated with the connection");
}
else if (mType == Stmt_Used) {
*desc = ::strdup("Memory (approximate) used by all prepared statements");
desc.AssignLiteral("Memory (approximate) used by all prepared statements");
}
return NS_OK;
}

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

@ -136,7 +136,7 @@ class RemoteOptions(MochitestOptions):
return None
if (options.remoteLogFile == None):
options.remoteLogFile = options.remoteTestRoot + '/mochitest.log'
options.remoteLogFile = options.remoteTestRoot + '/logs/mochitest.log'
if (options.remoteLogFile.count('/') < 1):
options.remoteLogFile = options.remoteTestRoot + '/' + options.remoteLogFile
@ -336,6 +336,8 @@ def main():
if (options == None):
sys.exit(1)
logParent = os.path.dirname(options.remoteLogFile)
dm.mkDir(logParent);
auto.setRemoteLog(options.remoteLogFile)
auto.setServerInfo(options.webServer, options.httpPort, options.sslPort)

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

@ -61,6 +61,13 @@ RUN_MOCHITEST = \
--console-level=INFO --log-file=./$@.log --file-level=INFO \
$(SYMBOLS_PATH) $(TEST_PATH_ARG) $(EXTRA_TEST_ARGS)
RUN_MOCHITEST_REMOTE = \
rm -f ./$@.log && \
$(PYTHON) _tests/testing/mochitest/runtestsremote.py --autorun --close-when-done \
--console-level=INFO --log-file=./$@.log --file-level=INFO $(DM_FLAGS) \
--app=$(ANDROID_PACKAGE_NAME) --deviceIP=${TEST_DEVICE} --xre-path=${MOZ_HOST_BIN} \
$(SYMBOLS_PATH) $(TEST_PATH_ARG) $(EXTRA_TEST_ARGS)
ifndef NO_FAIL_ON_TEST_ERRORS
define CHECK_TEST_ERROR
@errors=`grep "TEST-UNEXPECTED-" $@.log` ;\
@ -74,6 +81,13 @@ define CHECK_TEST_ERROR
endef
endif
mochitest-remote:
if test -f ${MOZ_HOST_BIN}/xpcshell && [ "${TEST_DEVICE}" != "" ]; \
then $(RUN_MOCHITEST_REMOTE); \
else \
@echo "please prepare your host with environment variables for TEST_DEVICE and MOZ_HOST_BIN"; \
fi
mochitest-plain:
$(RUN_MOCHITEST)
$(CHECK_TEST_ERROR)

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

@ -190,8 +190,6 @@ _BROWSER_TEST_PAGES = \
test-bug-595934-malformedxml-external.xml \
test-bug-595934-empty-getelementbyid.html \
test-bug-595934-empty-getelementbyid.js \
test-bug-595934-getselection.html \
test-bug-595934-getselection.js \
test-bug-595934-image.html \
test-bug-595934-image.jpg \
test-bug-597136-external-script-errors.html \

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

@ -89,11 +89,6 @@ const TESTS = [
category: "CSS Parser",
matchString: "foobarCanvasCssParser",
},
{ // #15
file: "test-bug-595934-getselection.html",
category: "content javascript",
matchString: "getSelection",
},
{ // #16
file: "test-bug-595934-image.html",
category: "Image",

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

@ -1,16 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Web Console test for bug 595934 - category: content javascript.
(getSelection())</title>
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<script type="text/javascript"
src="test-bug-595934-getselection.js"></script>
</head>
<body>
<p>Web Console test for bug 595934 - category "content javascript"
(getSelection()).</p>
</body>
</html>

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

@ -1,9 +0,0 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*/
window.addEventListener("load", function() {
document.getSelection();
}, false);

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

@ -445,7 +445,8 @@ bool ExceptionHandler::DoDump(pid_t crashing_process, const void* context,
crashing_process,
context,
context_size,
mapping_info_);
mapping_info_,
app_memory_info_);
}
// static
@ -539,4 +540,19 @@ void ExceptionHandler::AddMappingInfo(const std::string& name,
mapping_info_.push_back(mapping);
}
void ExceptionHandler::RegisterAppMemory(void *ptr, size_t length) {
app_memory_info_.push_back(AppMemory(ptr, length));
}
void ExceptionHandler::UnregisterAppMemory(void *ptr) {
for (AppMemoryList::iterator iter = app_memory_info_.begin();
iter != app_memory_info_.end();
++iter) {
if (iter->ptr == ptr) {
app_memory_info_.erase(iter);
return;
}
}
}
} // namespace google_breakpad

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

@ -219,6 +219,11 @@ class ExceptionHandler {
size_t mapping_size,
size_t file_offset);
// Calling RegisterAppMemory(p, len) causes len bytes starting
// at address p to be copied to the minidump when a crash happens.
void RegisterAppMemory(void *ptr, size_t length);
void UnregisterAppMemory(void *ptr);
private:
void Init(const std::string &dump_path,
const int server_fd);
@ -278,6 +283,10 @@ class ExceptionHandler {
// Callers can add extra info about mappings for cases where the
// dumper code cannot extract enough information from /proc/<pid>/maps.
MappingList mapping_info_;
// Callers can request additional memory regions to be included in
// the dump.
AppMemoryList app_memory_info_;
};
} // namespace google_breakpad

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

@ -418,7 +418,8 @@ class MinidumpWriter {
MinidumpWriter(const char* filename,
pid_t crashing_pid,
const ExceptionHandler::CrashContext* context,
const MappingList& mappings)
const MappingList& mappings,
const AppMemoryList& appmem)
: filename_(filename),
siginfo_(&context->siginfo),
ucontext_(&context->context),
@ -432,14 +433,16 @@ class MinidumpWriter {
crashing_tid_pc_(0),
dumper_(crashing_pid),
memory_blocks_(dumper_.allocator()),
mapping_info_(mappings) {
mapping_info_(mappings),
app_memory_info_(appmem) {
}
// case (2) above
MinidumpWriter(const char* filename,
pid_t pid,
pid_t blame_thread,
const MappingList& mappings)
const MappingList& mappings,
const AppMemoryList& appmem)
: filename_(filename),
siginfo_(NULL), // we fill this in if we find blame_thread
ucontext_(NULL),
@ -448,7 +451,8 @@ class MinidumpWriter {
crashing_tid_pc_(0), // set if we find blame_thread
dumper_(pid),
memory_blocks_(dumper_.allocator()),
mapping_info_(mappings) {
mapping_info_(mappings),
app_memory_info_(appmem) {
}
bool Init() {
@ -515,6 +519,9 @@ class MinidumpWriter {
return false;
dir.CopyIndex(dir_index++, &dirent);
if (!WriteAppMemory())
return false;
if (!WriteMemoryListStream(&dirent))
return false;
dir.CopyIndex(dir_index++, &dirent);
@ -824,6 +831,28 @@ class MinidumpWriter {
return true;
}
bool WriteAppMemory() {
for (AppMemoryList::const_iterator iter = app_memory_info_.begin();
iter != app_memory_info_.end();
++iter) {
uint8_t* data_copy =
(uint8_t*) dumper_.allocator()->Alloc(iter->length);
dumper_.CopyFromProcess(data_copy, crashing_tid_, iter->ptr,
iter->length);
UntypedMDRVA memory(&minidump_writer_);
if (!memory.Allocate(iter->length))
return false;
memory.Copy(data_copy, iter->length);
MDMemoryDescriptor desc;
desc.start_of_memory_range = (uintptr_t)iter->ptr;
desc.memory = memory.location();
memory_blocks_.push_back(desc);
}
return true;
}
static bool ShouldIncludeMapping(const MappingInfo& mapping) {
if (mapping.name[0] == 0 || // we only want modules with filenames.
mapping.offset || // we only want to include one mapping per shared lib.
@ -1362,22 +1391,27 @@ popline:
wasteful_vector<MDMemoryDescriptor> memory_blocks_;
// Additional information about some mappings provided by the caller.
const MappingList& mapping_info_;
// Callers can request additional memory regions to be included in
// the dump.
const AppMemoryList& app_memory_info_;
};
bool WriteMinidump(const char* filename, pid_t crashing_process,
const void* blob, size_t blob_size) {
MappingList m;
return WriteMinidump(filename, crashing_process, blob, blob_size, m);
AppMemoryList a;
return WriteMinidump(filename, crashing_process, blob, blob_size, m, a);
}
bool WriteMinidump(const char* filename, pid_t crashing_process,
const void* blob, size_t blob_size,
const MappingList& mappings) {
const MappingList& mappings,
const AppMemoryList& appmem) {
if (blob_size != sizeof(ExceptionHandler::CrashContext))
return false;
const ExceptionHandler::CrashContext* context =
reinterpret_cast<const ExceptionHandler::CrashContext*>(blob);
MinidumpWriter writer(filename, crashing_process, context, mappings);
MinidumpWriter writer(filename, crashing_process, context, mappings, appmem);
if (!writer.Init())
return false;
return writer.Dump();
@ -1387,7 +1421,8 @@ bool WriteMinidump(const char* filename, pid_t process,
pid_t process_blamed_thread) {
//TODO: support mappings here
MappingList m;
MinidumpWriter writer(filename, process, process_blamed_thread, m);
AppMemoryList a;
MinidumpWriter writer(filename, process, process_blamed_thread, m, a);
if (!writer.Init())
return false;
return writer.Dump();

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

@ -44,6 +44,16 @@ namespace google_breakpad {
typedef std::pair<struct MappingInfo, u_int8_t[sizeof(MDGUID)]> MappingEntry;
typedef std::list<MappingEntry> MappingList;
// These entries store a list of memory regions that the client wants included
// in the minidump.
struct AppMemory {
AppMemory(void *ptr, size_t length) : ptr(ptr), length(length) {}
void *ptr;
size_t length;
};
typedef std::list<AppMemory> AppMemoryList;
// Write a minidump to the filesystem. This function does not malloc nor use
// libc functions which may. Thus, it can be used in contexts where the state
// of the heap may be corrupt.
@ -65,10 +75,12 @@ bool WriteMinidump(const char* filename, pid_t crashing_process,
bool WriteMinidump(const char* filename, pid_t process,
pid_t process_blamed_thread);
// This overload also allows passing a list of known mappings.
// This overload also allows passing a list of known mappings and
// a list of additional memory regions to be included in the minidump.
bool WriteMinidump(const char* filename, pid_t crashing_process,
const void* blob, size_t blob_size,
const MappingList& mappings);
const MappingList& mappings,
const AppMemoryList& appdata);
} // namespace google_breakpad

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

@ -133,9 +133,7 @@ static const int kExceptionHandlerThreadInitialStackSize = 64 * 1024;
// This is passed as the context to the MinidumpWriteDump callback.
typedef struct {
ULONG64 memory_base;
ULONG memory_size;
bool finished;
AppMemoryList::const_iterator iter, end;
} MinidumpCallbackContext;
vector<ExceptionHandler*>* ExceptionHandler::handler_stack_ = NULL;
@ -926,13 +924,13 @@ BOOL CALLBACK ExceptionHandler::MinidumpWriteDumpCallback(
case MemoryCallback: {
MinidumpCallbackContext* callback_context =
reinterpret_cast<MinidumpCallbackContext*>(context);
if (callback_context->finished)
if (callback_context->iter == callback_context->end)
return FALSE;
// Include the specified memory region.
callback_output->MemoryBase = callback_context->memory_base;
callback_output->MemorySize = callback_context->memory_size;
callback_context->finished = true;
callback_output->MemoryBase = callback_context->iter->ptr;
callback_output->MemorySize = callback_context->iter->length;
callback_context->iter++;
return TRUE;
}
@ -1015,9 +1013,6 @@ bool ExceptionHandler::WriteMinidumpWithExceptionForProcess(
++user_streams.UserStreamCount;
}
MINIDUMP_CALLBACK_INFORMATION callback;
MinidumpCallbackContext context;
MINIDUMP_CALLBACK_INFORMATION* callback_pointer = NULL;
// Older versions of DbgHelp.dll don't correctly put the memory around
// the faulting instruction pointer into the minidump. This
// callback will ensure that it gets included.
@ -1042,23 +1037,26 @@ bool ExceptionHandler::WriteMinidumpWithExceptionForProcess(
// pointer, but settle for whatever's available up to the
// boundaries of the memory region.
const ULONG64 kIPMemorySize = 256;
context.memory_base =
ULONG64 base =
std::max(reinterpret_cast<ULONG64>(info.BaseAddress),
instruction_pointer - (kIPMemorySize / 2));
ULONG64 end_of_range =
std::min(instruction_pointer + (kIPMemorySize / 2),
reinterpret_cast<ULONG64>(info.BaseAddress)
+ info.RegionSize);
context.memory_size =
static_cast<ULONG>(end_of_range - context.memory_base);
context.finished = false;
callback.CallbackRoutine = MinidumpWriteDumpCallback;
callback.CallbackParam = reinterpret_cast<void*>(&context);
callback_pointer = &callback;
ULONG size = static_cast<ULONG>(end_of_range - base);
app_memory_info_.push_back(AppMemory(base, size));
}
}
MinidumpCallbackContext context;
context.iter = app_memory_info_.begin();
context.end = app_memory_info_.end();
MINIDUMP_CALLBACK_INFORMATION callback;
callback.CallbackRoutine = MinidumpWriteDumpCallback;
callback.CallbackParam = reinterpret_cast<void*>(&context);
// The explicit comparison to TRUE avoids a warning (C4800).
success = (minidump_write_dump_(process,
processId,
@ -1066,7 +1064,7 @@ bool ExceptionHandler::WriteMinidumpWithExceptionForProcess(
dump_type_,
exinfo ? &except_info : NULL,
&user_streams,
callback_pointer) == TRUE);
&callback) == TRUE);
CloseHandle(dump_file);
}
@ -1095,4 +1093,20 @@ void ExceptionHandler::UpdateNextID() {
next_minidump_path_c_ = next_minidump_path_.c_str();
}
void ExceptionHandler::RegisterAppMemory(void *ptr, size_t length) {
app_memory_info_.push_back(AppMemory(reinterpret_cast<ULONG64>(ptr),
static_cast<ULONG>(length)));
}
void ExceptionHandler::UnregisterAppMemory(void *ptr) {
for (AppMemoryList::iterator iter = app_memory_info_.begin();
iter != app_memory_info_.end();
++iter) {
if (iter->ptr == reinterpret_cast<ULONG64>(ptr)) {
app_memory_info_.erase(iter);
return;
}
}
}
} // namespace google_breakpad

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

@ -67,6 +67,7 @@
#include <string>
#include <vector>
#include <list>
#include "client/windows/common/ipc_protocol.h"
#include "client/windows/crash_generation/crash_generation_client.h"
@ -78,6 +79,16 @@ namespace google_breakpad {
using std::vector;
using std::wstring;
// These entries store a list of memory regions that the client wants included
// in the minidump.
struct AppMemory {
AppMemory(ULONG64 ptr, ULONG length) : ptr(ptr), length(length) {}
ULONG64 ptr;
ULONG length;
};
typedef std::list<AppMemory> AppMemoryList;
class ExceptionHandler {
public:
// A callback function to run before Breakpad performs any substantial
@ -222,6 +233,11 @@ class ExceptionHandler {
// Returns whether out-of-process dump generation is used or not.
bool IsOutOfProcess() const { return crash_generation_client_.get() != NULL; }
// Calling RegisterAppMemory(p, len) causes len bytes starting
// at address p to be copied to the minidump when a crash happens.
void RegisterAppMemory(void *ptr, size_t length);
void UnregisterAppMemory(void *ptr);
private:
friend class AutoExceptionHandler;
@ -422,6 +438,10 @@ class ExceptionHandler {
// to not interfere with debuggers.
bool handle_debug_exceptions_;
// Callers can request additional memory regions to be included in
// the dump.
AppMemoryList app_memory_info_;
// A stack of ExceptionHandler objects that have installed unhandled
// exception filters. This vector is used by HandleException to determine
// which ExceptionHandler object to route an exception to. When an

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

@ -1153,6 +1153,32 @@ bool GetAnnotation(const nsACString& key, nsACString& data)
return true;
}
nsresult RegisterAppMemory(void* ptr, size_t length)
{
if (!GetEnabled())
return NS_ERROR_NOT_INITIALIZED;
#if defined(XP_LINUX) || defined(XP_WIN32)
gExceptionHandler->RegisterAppMemory(ptr, length);
return NS_OK;
#else
return NS_ERROR_NOT_IMPLEMENTED;
#endif
}
nsresult UnregisterAppMemory(void* ptr)
{
if (!GetEnabled())
return NS_ERROR_NOT_INITIALIZED;
#if defined(XP_LINUX) || defined(XP_WIN32)
gExceptionHandler->UnregisterAppMemory(ptr);
return NS_OK;
#else
return NS_ERROR_NOT_IMPLEMENTED;
#endif
}
bool GetServerURL(nsACString& aServerURL)
{
if (!gExceptionHandler)
@ -1689,6 +1715,7 @@ OnChildProcessDumpRequested(void* aContext,
// have access to the library mappings.
MappingMap::const_iterator iter =
child_library_mappings.find(aClientInfo->pid_);
google_breakpad::AppMemoryList a;
if (iter == child_library_mappings.end()) {
NS_WARNING("No library mappings found for child, can't write minidump!");
return;
@ -1698,7 +1725,8 @@ OnChildProcessDumpRequested(void* aContext,
aClientInfo->pid_,
aClientInfo->crash_context,
aClientInfo->crash_context_size,
iter->second))
iter->second,
a))
return;
#endif

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

@ -70,6 +70,10 @@ nsresult SetRestartArgs(int argc, char** argv);
nsresult SetupExtraData(nsILocalFile* aAppDataDirectory,
const nsACString& aBuildID);
// Registers an additional memory region to be included in the minidump
nsresult RegisterAppMemory(void* ptr, size_t length);
nsresult UnregisterAppMemory(void* ptr);
// Functions for working with minidumps and .extras
typedef nsDataHashtable<nsCStringHashKey, nsCString> AnnotationTable;

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

@ -29,6 +29,9 @@ CrashTestUtils.crash = lib.declare("Crash",
ctypes.default_abi,
ctypes.void_t,
ctypes.int16_t);
CrashTestUtils.saveAppMemory = lib.declare("SaveAppMemory",
ctypes.default_abi,
ctypes.uint64_t);
CrashTestUtils.lockDir = lib.declare("LockDir",
ctypes.default_abi,
@ -47,3 +50,8 @@ CrashTestUtils.dumpHasInstructionPointerMemory =
ctypes.default_abi,
ctypes.bool,
ctypes.char.ptr);
CrashTestUtils.dumpCheckMemory = lib.declare("DumpCheckMemory",
ctypes.default_abi,
ctypes.bool,
ctypes.char.ptr);

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

@ -1,3 +1,5 @@
#include <stdio.h>
#include "google_breakpad/processor/minidump.h"
#include "nscore.h"
@ -58,3 +60,48 @@ DumpHasInstructionPointerMemory(const char* dump_file)
memory_list->GetMemoryRegionForAddress(instruction_pointer);
return region != NULL;
}
// This function tests for a very specific condition. It finds
// an address in a file, "crash-addr", in the CWD. It checks
// that the minidump has a memory region starting at that
// address. The region must be 32 bytes long and contain the
// values 0 to 31 as bytes, in ascending order.
extern "C"
NS_EXPORT bool
DumpCheckMemory(const char* dump_file)
{
Minidump dump(dump_file);
if (!dump.Read())
return false;
MinidumpMemoryList* memory_list = dump.GetMemoryList();
if (!memory_list) {
return false;
}
void *addr;
FILE *fp = fopen("crash-addr", "r");
if (!fp)
return false;
if (fscanf(fp, "%p", &addr) != 1)
return false;
fclose(fp);
remove("crash-addr");
MinidumpMemoryRegion* region =
memory_list->GetMemoryRegionForAddress(u_int64_t(addr));
if(!region)
return false;
const u_int8_t* chars = region->GetMemory();
if (region->GetSize() != 32)
return false;
for (int i=0; i<32; i++) {
if (chars[i] != i)
return false;
}
return true;
}

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

@ -1,5 +1,8 @@
#include <stdio.h>
#include "nscore.h"
#include "nsXULAppAPI.h"
#include "nsExceptionHandler.h"
/*
* This pure virtual call example is from MSDN
@ -67,3 +70,20 @@ nsISupports* LockDir(nsILocalFile *directory)
XRE_LockProfileDirectory(directory, &lockfile);
return lockfile;
}
char testData[32];
extern "C" NS_EXPORT
PRUint64 SaveAppMemory()
{
for (size_t i=0; i<sizeof(testData); i++)
testData[i] = i;
FILE *fp = fopen("crash-addr", "w");
if (!fp)
return 0;
fprintf(fp, "%p\n", (void *)testData);
fclose(fp);
return (PRInt64)testData;
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше