merge fx-team to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2014-06-25 15:34:21 +02:00
commit 9bf09b73ad
52 changed files with 1057 additions and 347 deletions

View File

@ -45,6 +45,7 @@ support-files =
doc_closure-optimized-out.html
doc_cmd-break.html
doc_cmd-dbg.html
doc_breakpoint-move.html
doc_conditional-breakpoints.html
doc_domnode-variables.html
doc_editor-mode.html
@ -116,6 +117,7 @@ skip-if = os == 'win' # bug 1005274
[browser_dbg_break-on-dom-event.js]
skip-if = os == "mac" || e10s # Bug 895426
[browser_dbg_breakpoints-actual-location.js]
[browser_dbg_breakpoints-actual-location2.js]
[browser_dbg_breakpoints-break-on-last-line-of-script-on-reload.js]
[browser_dbg_breakpoints-button-01.js]
[browser_dbg_breakpoints-button-02.js]

View File

@ -0,0 +1,103 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Bug 1008372: Setting a breakpoint in a line without code should move
* the icon to the actual location, and if a breakpoint already exists
* on the new location don't duplicate
*/
const TAB_URL = EXAMPLE_URL + "doc_breakpoint-move.html";
function test() {
let gTab, gDebuggee, gPanel, gDebugger;
let gEditor, gSources, gBreakpoints, gBreakpointsAdded, gBreakpointsRemoving;
initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
gTab = aTab;
gDebuggee = aDebuggee;
gPanel = aPanel;
gDebugger = gPanel.panelWin;
gEditor = gDebugger.DebuggerView.editor;
gSources = gDebugger.DebuggerView.Sources;
gBreakpoints = gDebugger.DebuggerController.Breakpoints;
gBreakpointsAdded = gBreakpoints._added;
gBreakpointsRemoving = gBreakpoints._removing;
waitForSourceAndCaretAndScopes(gPanel, ".html", 1).then(performTest);
gDebuggee.ermahgerd();
});
function performTest() {
is(gBreakpointsAdded.size, 0,
"No breakpoints currently added.");
is(gBreakpointsRemoving.size, 0,
"No breakpoints currently being removed.");
is(gEditor.getBreakpoints().length, 0,
"No breakpoints currently shown in the editor.");
Task.spawn(function*() {
let bpClient = yield gPanel.addBreakpoint({
url: gSources.selectedValue,
line: 19
});
yield gPanel.addBreakpoint({
url: gSources.selectedValue,
line: 20
});
let movedBpClient = yield gPanel.addBreakpoint({
url: gSources.selectedValue,
line: 17
});
testMovedLocation(movedBpClient);
yield resumeAndTestBreakpoint(19);
yield gPanel.removeBreakpoint({
url: gSources.selectedValue,
line: 19
});
yield resumeAndTestBreakpoint(20);
yield doResume(gPanel);
executeSoon(() => gDebuggee.ermahgerd());
yield waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_SCOPES);
yield resumeAndTestBreakpoint(20);
resumeDebuggerThenCloseAndFinish(gPanel);
});
}
function resumeAndTestBreakpoint(line) {
return Task.spawn(function*() {
let event = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_SCOPES);
doResume(gPanel);
yield event;
testBreakpoint(line);
});
};
function testBreakpoint(line) {
let selectedBreakpoint = gSources._selectedBreakpointItem;
ok(selectedBreakpoint,
"There should be a selected breakpoint on line " + line);
is(selectedBreakpoint.attachment.line, line,
"The breakpoint on line " + line + " was not hit");
}
function testMovedLocation(breakpointClient) {
ok(breakpointClient,
"Breakpoint added, client received.");
is(breakpointClient.location.url, gSources.selectedValue,
"Breakpoint client url is the same.");
is(breakpointClient.location.line, 19,
"Breakpoint client line is new.");
is(breakpointClient.requestedLocation.url, gSources.selectedValue,
"Requested location url is correct");
is(breakpointClient.requestedLocation.line, 17,
"Requested location line is correct");
}
}

View File

@ -0,0 +1,25 @@
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<!doctype html>
<html>
<head>
<meta charset="utf-8"/>
<title>Debugger test page</title>
</head>
<body>
<button onclick="ermahgerd()">Click me!</button>
<script type="text/javascript">
function ermahgerd() {
debugger;
// This is just a line
// and here we are
var x = 5;
return x;
}
</script>
</body>
</html>

View File

@ -35,7 +35,7 @@ function test() {
function testPrefs() {
let { Prefs } = aMonitor.panelWin;
is(Prefs.root, "devtools.netmonitor",
is(Prefs._root, "devtools.netmonitor",
"The preferences object should have a correct root path.");
is(Prefs.networkDetailsWidth,

View File

@ -1,5 +1,4 @@
[DEFAULT]
skip-if = os == "win" && !debug # Bug 1014046
subsuite = devtools
support-files =
head.js

View File

@ -121,7 +121,7 @@ function buildTempDirectoryStructure() {
let htmlFile = FileUtils.getFile("TmpD", ["ProjectEditor", "index.html"]);
htmlFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
writeToFile(htmlFile, [
writeToFileSync(htmlFile, [
'<!DOCTYPE html>',
'<html lang="en">',
' <head>',
@ -137,14 +137,14 @@ function buildTempDirectoryStructure() {
let readmeFile = FileUtils.getFile("TmpD", ["ProjectEditor", "README.md"]);
readmeFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
writeToFile(readmeFile, [
writeToFileSync(readmeFile, [
'## Readme'
].join("\n")
);
let licenseFile = FileUtils.getFile("TmpD", ["ProjectEditor", "LICENSE"]);
licenseFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
writeToFile(licenseFile, [
writeToFileSync(licenseFile, [
'/* This Source Code Form is subject to the terms of the Mozilla Public',
' * License, v. 2.0. If a copy of the MPL was not distributed with this',
' * file, You can obtain one at http://mozilla.org/MPL/2.0/. */'
@ -153,7 +153,7 @@ function buildTempDirectoryStructure() {
let cssFile = FileUtils.getFile("TmpD", ["ProjectEditor", "css", "styles.css"]);
cssFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
writeToFile(cssFile, [
writeToFileSync(cssFile, [
'body {',
' background: red;',
'}'
@ -191,6 +191,29 @@ function writeToFile(file, data) {
});
}
// This is used when setting up the test.
// You should typically use the async version of this, writeToFile.
// https://developer.mozilla.org/en-US/Add-ons/Code_snippets/File_I_O#More
function writeToFileSync(file, data) {
// file is nsIFile, data is a string
var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"].
createInstance(Components.interfaces.nsIFileOutputStream);
// use 0x02 | 0x10 to open file for appending.
foStream.init(file, 0x02 | 0x08 | 0x20, 0666, 0);
// write, create, truncate
// In a c file operation, we have no need to set file mode with or operation,
// directly using "r" or "w" usually.
// if you are sure there will never ever be any non-ascii text in data you can
// also call foStream.write(data, data.length) directly
var converter = Components.classes["@mozilla.org/intl/converter-output-stream;1"].
createInstance(Components.interfaces.nsIConverterOutputStream);
converter.init(foStream, "UTF-8", 0, 0);
converter.writeString(data);
converter.close(); // this closes foStream
}
function getTempFile(path) {
let parts = ["ProjectEditor"];
parts = parts.concat(path.split("/"));

View File

@ -29,8 +29,10 @@ support-files =
[browser_graphs-14.js]
[browser_layoutHelpers.js]
[browser_layoutHelpers-getBoxQuads.js]
[browser_num-l10n.js]
[browser_observableobject.js]
[browser_outputparser.js]
[browser_prefs.js]
[browser_require_basic.js]
[browser_spectrum.js]
[browser_tableWidget_basic.js]

View File

@ -0,0 +1,25 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests that ViewHelpers.Prefs work properly.
let {ViewHelpers} = Cu.import("resource:///modules/devtools/ViewHelpers.jsm", {});
function test() {
let l10n = new ViewHelpers.L10N();
is(l10n.numberWithDecimals(1234.56789, 2), "1,234.56",
"The first number was properly localized.");
is(l10n.numberWithDecimals(0.0001, 2), "0",
"The second number was properly localized.");
is(l10n.numberWithDecimals(1.0001, 2), "1",
"The third number was properly localized.");
is(l10n.numberWithDecimals(NaN, 2), "0",
"NaN was properly localized.");
is(l10n.numberWithDecimals(null, 2), "0",
"`null` was properly localized.");
is(l10n.numberWithDecimals(undefined, 2), "0",
"`undefined` was properly localized.");
finish();
}

View File

@ -0,0 +1,33 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Tests that ViewHelpers.Prefs work properly.
let {ViewHelpers} = Cu.import("resource:///modules/devtools/ViewHelpers.jsm", {});
function test() {
let Prefs = new ViewHelpers.Prefs("devtools.debugger", {
"foo": ["Bool", "enabled"]
});
let originalPrefValue = Services.prefs.getBoolPref("devtools.debugger.enabled");
is(Prefs.foo, originalPrefValue, "The pref value was correctly fetched.");
Prefs.foo = !originalPrefValue;
is(Prefs.foo, !originalPrefValue,
"The pref was was correctly changed (1).");
is(Services.prefs.getBoolPref("devtools.debugger.enabled"), !originalPrefValue,
"The pref was was correctly changed (2).");
Services.prefs.setBoolPref("devtools.debugger.enabled", originalPrefValue);
info("The pref value was reset.");
is(Prefs.foo, !originalPrefValue,
"The cached pref value hasn't changed yet.");
Prefs.refresh();
is(Prefs.foo, originalPrefValue,
"The cached pref value has changed now.");
finish();
}

View File

@ -365,11 +365,21 @@ ViewHelpers.L10N.prototype = {
if (aNumber == (aNumber | 0)) {
return aNumber;
}
if (isNaN(aNumber) || aNumber == null) {
return "0";
}
// Remove {n} trailing decimals. Can't use toFixed(n) because
// toLocaleString converts the number to a string. Also can't use
// toLocaleString(, { maximumFractionDigits: n }) because it's not
// implemented on OS X (bug 368838). Gross.
let localized = aNumber.toLocaleString(); // localize
// If no grouping or decimal separators are available, bail out, because
// padding with zeros at the end of the string won't make sense anymore.
if (!localized.match(/[^\d]/)) {
return localized;
}
let padded = localized + new Array(aDecimals).join("0"); // pad with zeros
let match = padded.match("([^]*?\\d{" + aDecimals + "})\\d*$");
return match.pop();
@ -394,7 +404,8 @@ ViewHelpers.L10N.prototype = {
* An object containing { accessorName: [prefType, prefName] } keys.
*/
ViewHelpers.Prefs = function(aPrefsRoot = "", aPrefsObject = {}) {
this.root = aPrefsRoot;
this._root = aPrefsRoot;
this._cache = new Map();
for (let accessorName in aPrefsObject) {
let [prefType, prefName] = aPrefsObject[accessorName];
@ -411,10 +422,13 @@ ViewHelpers.Prefs.prototype = {
* @return any
*/
_get: function(aType, aPrefName) {
if (this[aPrefName] === undefined) {
this[aPrefName] = Services.prefs["get" + aType + "Pref"](aPrefName);
let cachedPref = this._cache.get(aPrefName);
if (cachedPref !== undefined) {
return cachedPref;
}
return this[aPrefName];
let value = Services.prefs["get" + aType + "Pref"](aPrefName);
this._cache.set(aPrefName, value);
return value;
},
/**
@ -426,7 +440,7 @@ ViewHelpers.Prefs.prototype = {
*/
_set: function(aType, aPrefName, aValue) {
Services.prefs["set" + aType + "Pref"](aPrefName, aValue);
this[aPrefName] = aValue;
this._cache.set(aPrefName, aValue);
},
/**
@ -446,9 +460,16 @@ ViewHelpers.Prefs.prototype = {
}
Object.defineProperty(this, aAccessorName, {
get: () => aSerializer.in(this._get(aType, [this.root, aPrefName].join("."))),
set: (e) => this._set(aType, [this.root, aPrefName].join("."), aSerializer.out(e))
get: () => aSerializer.in(this._get(aType, [this._root, aPrefName].join("."))),
set: (e) => this._set(aType, [this._root, aPrefName].join("."), aSerializer.out(e))
});
},
/**
* Clears all the cached preferences' values.
*/
refresh: function() {
this._cache.clear();
}
};

View File

@ -20,6 +20,8 @@ support-files =
[browser_webaudio-actor-simple.js]
[browser_webaudio-actor-destroy-node.js]
[browser_wa_destroy-node-01.js]
[browser_wa_first-run.js]
[browser_wa_reset-01.js]
[browser_wa_reset-02.js]

View File

@ -0,0 +1,62 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that the destruction node event is fired and that the nodes are no
* longer stored internally in the tool, that the graph is updated properly, and
* that selecting a soon-to-be dead node clears the inspector.
*
* All done in one test since this test takes a few seconds to clear GC.
*/
function spawnTest() {
let [target, debuggee, panel] = yield initWebAudioEditor(DESTROY_NODES_URL);
let { panelWin } = panel;
let { gFront, $, $$, EVENTS } = panelWin;
let started = once(gFront, "start-context");
reload(target);
let destroyed = getN(panelWin, EVENTS.DESTROY_NODE, 10);
forceCC();
let [created] = yield Promise.all([
getNSpread(panelWin, EVENTS.CREATE_NODE, 13),
waitForGraphRendered(panelWin, 13, 2)
]);
// Since CREATE_NODE emits several arguments (eventName and actorID), let's
// flatten it to just the actorIDs
let actorIDs = created.map(ev => ev[1]);
// Click a soon-to-be dead buffer node
yield clickGraphNode(panelWin, actorIDs[5]);
forceCC();
// Wait for destruction and graph to re-render
yield Promise.all([destroyed, waitForGraphRendered(panelWin, 3, 2)]);
// Test internal storage
ok(panelWin.AudioNodes.length, 3, "All nodes should be GC'd except one gain, osc and dest node.");
// Test graph rendering
ok(findGraphNode(panelWin, actorIDs[0]), "dest should be in graph");
ok(findGraphNode(panelWin, actorIDs[1]), "osc should be in graph");
ok(findGraphNode(panelWin, actorIDs[2]), "gain should be in graph");
let { nodes, edges } = countGraphObjects(panelWin);
is(nodes, 3, "Only 3 nodes rendered in graph.");
is(edges, 2, "Only 2 edges rendered in graph.");
// Test that the inspector reset to no node selected
ok(isVisible($("#web-audio-editor-details-pane-empty")),
"InspectorView empty message should show if the currently selected node gets collected.");
yield teardown(panel);
finish();
}

View File

@ -156,6 +156,7 @@ let WebAudioEditorController = {
gFront.on("connect-node", this._onConnectNode);
gFront.on("disconnect-node", this._onDisconnectNode);
gFront.on("change-param", this._onChangeParam);
gFront.on("destroy-node", this._onDestroyNode);
// Hook into theme change so we can change
// the graph's marker styling, since we can't do this
@ -166,6 +167,7 @@ let WebAudioEditorController = {
window.on(EVENTS.CREATE_NODE, this._onUpdatedContext);
window.on(EVENTS.CONNECT_NODE, this._onUpdatedContext);
window.on(EVENTS.DISCONNECT_NODE, this._onUpdatedContext);
window.on(EVENTS.DESTROY_NODE, this._onUpdatedContext);
},
/**
@ -180,9 +182,11 @@ let WebAudioEditorController = {
gFront.off("connect-node", this._onConnectNode);
gFront.off("disconnect-node", this._onDisconnectNode);
gFront.off("change-param", this._onChangeParam);
gFront.off("destroy-node", this._onDestroyNode);
window.off(EVENTS.CREATE_NODE, this._onUpdatedContext);
window.off(EVENTS.CONNECT_NODE, this._onUpdatedContext);
window.off(EVENTS.DISCONNECT_NODE, this._onUpdatedContext);
window.off(EVENTS.DESTROY_NODE, this._onUpdatedContext);
gDevTools.off("pref-changed", this._onThemeChange);
},
@ -264,6 +268,20 @@ let WebAudioEditorController = {
window.emit(EVENTS.CREATE_NODE, node.id);
}),
/**
* Called on `destroy-node` when an AudioNode is GC'd. Removes
* from the AudioNode array and fires an event indicating the removal.
*/
_onDestroyNode: function (nodeActor) {
for (let i = 0; i < AudioNodes.length; i++) {
if (equalActors(AudioNodes[i].actor, nodeActor)) {
AudioNodes.splice(i, 1);
window.emit(EVENTS.DESTROY_NODE, nodeActor.actorID);
break;
}
}
},
/**
* Called when a node is connected to another node.
*/

View File

@ -54,6 +54,7 @@ let WebAudioGraphView = {
this._onThemeChange = this._onThemeChange.bind(this);
this._onNodeSelect = this._onNodeSelect.bind(this);
this._onStartContext = this._onStartContext.bind(this);
this._onDestroyNode = this._onDestroyNode.bind(this);
this.draw = debounce(this.draw.bind(this), GRAPH_DEBOUNCE_TIMER);
$('#graph-target').addEventListener('click', this._onGraphNodeClick, false);
@ -61,6 +62,7 @@ let WebAudioGraphView = {
window.on(EVENTS.THEME_CHANGE, this._onThemeChange);
window.on(EVENTS.UI_INSPECTOR_NODE_SET, this._onNodeSelect);
window.on(EVENTS.START_CONTEXT, this._onStartContext);
window.on(EVENTS.DESTROY_NODE, this._onDestroyNode);
},
/**
@ -74,6 +76,7 @@ let WebAudioGraphView = {
window.off(EVENTS.THEME_CHANGE, this._onThemeChange);
window.off(EVENTS.UI_INSPECTOR_NODE_SET, this._onNodeSelect);
window.off(EVENTS.START_CONTEXT, this._onStartContext);
window.off(EVENTS.DESTROY_NODE, this._onDestroyNode);
},
/**
@ -232,6 +235,13 @@ let WebAudioGraphView = {
this.draw();
},
/**
* Called when a node gets GC'd -- redraws the graph.
*/
_onDestroyNode: function () {
this.draw();
},
_onNodeSelect: function (eventName, id) {
this.focusNode(id);
},
@ -289,12 +299,14 @@ let WebAudioInspectorView = {
this._onEval = this._onEval.bind(this);
this._onNodeSelect = this._onNodeSelect.bind(this);
this._onTogglePaneClick = this._onTogglePaneClick.bind(this);
this._onDestroyNode = this._onDestroyNode.bind(this);
this._inspectorPaneToggleButton.addEventListener("mousedown", this._onTogglePaneClick, false);
this._propsView = new VariablesView($("#properties-tabpanel-content"), GENERIC_VARIABLES_VIEW_SETTINGS);
this._propsView.eval = this._onEval;
window.on(EVENTS.UI_SELECT_NODE, this._onNodeSelect);
window.on(EVENTS.DESTROY_NODE, this._onDestroyNode);
},
/**
@ -303,6 +315,7 @@ let WebAudioInspectorView = {
destroy: function () {
this._inspectorPaneToggleButton.removeEventListener("mousedown", this._onTogglePaneClick);
window.off(EVENTS.UI_SELECT_NODE, this._onNodeSelect);
window.off(EVENTS.DESTROY_NODE, this._onDestroyNode);
this._inspectorPane = null;
this._inspectorPaneToggleButton = null;
@ -508,12 +521,14 @@ let WebAudioInspectorView = {
},
/**
* Called when `DESTROY_NODE` is fired to remove the node from props view.
* TODO bug 994263, dependent on node GC events
* Called when `DESTROY_NODE` is fired to remove the node from props view if
* it's currently selected.
*/
removeNode: Task.async(function* (viewNode) {
})
_onDestroyNode: function (_, id) {
if (this._currentNode && this._currentNode.id === id) {
this.setCurrentAudioNode(null);
}
}
};
/**

View File

@ -73,7 +73,9 @@ this.ContentSearch = {
// the meantime, then we need to update msg.target. event.detail will be
// the docshell's new parent <xul:browser> element.
msg.handleEvent = function (event) {
this.target.removeEventListener("SwapDocShells", this, true);
this.target = event.detail;
this.target.addEventListener("SwapDocShells", this, true);
};
msg.target.addEventListener("SwapDocShells", msg, true);

View File

@ -38,12 +38,6 @@ java-tests := \
$(wildcard $(TESTPATH)/components/*.java) \
$(wildcard $(TESTPATH)/helpers/*.java)
# pre-process TestConstants.java.in
PP_TARGETS += testconstants
testconstants-dep := $(dir-tests)/TestConstants.java
testconstants := $(TESTPATH)/TestConstants.java.in
testconstants_PATH := $(dir-tests)
PP_TARGETS += manifest
manifest := $(srcdir)/AndroidManifest.xml.in
manifest_TARGET := AndroidManifest.xml

View File

@ -9,9 +9,7 @@ DEFINES['ANDROID_PACKAGE_NAME'] = CONFIG['ANDROID_PACKAGE_NAME']
main = add_android_eclipse_project('Robocop', OBJDIR + '/AndroidManifest.xml')
main.package_name = 'org.mozilla.roboexample.test'
main.res = SRCDIR + '/res'
main.recursive_make_targets += [
OBJDIR + '/AndroidManifest.xml',
'../../../mobile/android/base/tests/TestConstants.java']
main.recursive_make_targets += [OBJDIR + '/AndroidManifest.xml']
main.extra_jars += [SRCDIR + '/robotium-solo-4.3.1.jar']
main.assets = TOPSRCDIR + '/mobile/android/base/tests/assets'
main.referenced_projects += ['Fennec']
@ -20,5 +18,3 @@ main.add_classpathentry('harness', SRCDIR,
dstdir='harness/org/mozilla/gecko')
main.add_classpathentry('src', TOPSRCDIR + '/mobile/android/base/tests',
dstdir='src/org/mozilla/gecko/tests')
main.add_classpathentry('generated', TOPOBJDIR + '/mobile/android/base/tests',
dstdir='generated/org/mozilla/gecko/tests')

View File

@ -95,7 +95,7 @@
<!-- If the windowSoftInputMode adjust* flag changes below, the
setSoftInputMode call in BrowserSearch#onStop must also be updated. -->
<activity android:name=".App"
<activity android:name="org.mozilla.gecko.BrowserApp"
android:label="@string/moz_app_displayname"
android:taskAffinity="@ANDROID_PACKAGE_NAME@.BROWSER"
android:alwaysRetainTaskState="true"
@ -103,7 +103,20 @@
android:windowSoftInputMode="stateUnspecified|adjustResize"
android:launchMode="singleTask"
android:theme="@style/Gecko.App">
</activity>
<!-- Fennec is shipped as the Android package named
org.mozilla.{fennec,firefox,firefox_beta}. The internal Java package
hierarchy inside the Android package has both an
org.mozilla.{fennec,firefox,firefox_beta} subtree *and* an
org.mozilla.gecko subtree. The non-org.mozilla.gecko is deprecated
and we would like to get rid of it entirely. Until that happens, we
have external consumers (such as intents and bookmarks) of
non-org.mozilla.gecko Activity classes, so we define activity aliases
for backwards compatibility. -->
<activity-alias android:name=".App"
android:label="@MOZ_APP_DISPLAYNAME@"
android:targetActivity="org.mozilla.gecko.BrowserApp">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
@ -196,7 +209,7 @@
<action android:name="org.mozilla.gecko.DEBUG" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</activity-alias>
<activity android:name="org.mozilla.gecko.webapp.Dispatcher"
android:noHistory="true" >
@ -222,7 +235,8 @@
</intent-filter>
</receiver>
<activity android:name=".Webapp"
<!-- Activity used for launching non-privileged WebApps via a URL -->
<activity android:name="org.mozilla.gecko.Webapp"
android:label="@string/webapp_generic_name"
android:configChanges="keyboard|keyboardHidden|mcc|mnc|orientation|screenSize"
android:windowSoftInputMode="stateUnspecified|adjustResize"
@ -231,13 +245,19 @@
android:process=":@ANDROID_PACKAGE_NAME@.Webapp"
android:excludeFromRecents="true"
android:theme="@style/Gecko.App">
</activity>
<!-- Alias Webapp so we can launch it from the package namespace. -->
<activity-alias android:name=".Webapp"
android:label="@string/webapp_generic_name"
android:targetActivity="org.mozilla.gecko.Webapp">
<intent-filter>
<action android:name="org.mozilla.gecko.WEBAPP" />
</intent-filter>
<intent-filter>
<action android:name="org.mozilla.gecko.ACTION_ALERT_CALLBACK" />
</intent-filter>
</activity>
</activity-alias>
<!-- Declare a predefined number of Webapp<num> activities. These are
used so that each web app can launch in its own process. Keep
@ -250,7 +270,7 @@
<!-- Masquerade as the Resolver so that we can be opened from the Marketplace. -->
<activity-alias
android:name="com.android.internal.app.ResolverActivity"
android:targetActivity=".App"
android:targetActivity="org.mozilla.gecko.BrowserApp"
android:exported="true" />
<receiver android:name="org.mozilla.gecko.GeckoUpdateReceiver">

View File

@ -1,15 +0,0 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#filter substitution
package @ANDROID_PACKAGE_NAME@;
import org.mozilla.gecko.BrowserApp;
/**
* This class serves only as a namespace wrapper for BrowserApp.
*/
public class App extends BrowserApp {}

View File

@ -25,7 +25,7 @@ public class AppConstants {
/**
* The name of the Java class that launches the browser.
*/
public static final String BROWSER_INTENT_CLASS_NAME = ANDROID_PACKAGE_NAME + ".App";
public static final String BROWSER_INTENT_CLASS_NAME = "org.mozilla.gecko.BrowserApp";
public static final String GRE_MILESTONE = "@GRE_MILESTONE@";

View File

@ -112,16 +112,16 @@ import android.widget.RelativeLayout;
import android.widget.Toast;
import android.widget.ViewFlipper;
abstract public class BrowserApp extends GeckoApp
implements TabsPanel.TabsLayoutChangeListener,
PropertyAnimator.PropertyAnimationListener,
View.OnKeyListener,
LayerView.OnMetricsChangedListener,
BrowserSearch.OnSearchListener,
BrowserSearch.OnEditSuggestionListener,
HomePager.OnNewTabsListener,
OnUrlOpenListener,
ActionModeCompat.Presenter {
public class BrowserApp extends GeckoApp
implements TabsPanel.TabsLayoutChangeListener,
PropertyAnimator.PropertyAnimationListener,
View.OnKeyListener,
LayerView.OnMetricsChangedListener,
BrowserSearch.OnSearchListener,
BrowserSearch.OnEditSuggestionListener,
HomePager.OnNewTabsListener,
OnUrlOpenListener,
ActionModeCompat.Presenter {
private static final String LOGTAG = "GeckoBrowserApp";
private static final int TABS_ANIMATION_DURATION = 450;

View File

@ -377,6 +377,22 @@ fennec_ids.txt: generated/org/mozilla/gecko/R.java fennec-ids-generator.py
# Override the Java settings with some specific android settings
include $(topsrcdir)/config/android-common.mk
# This target is only used by the Eclipse integration. It rebuilds
# resources that end up in omni.ja, does most of the packaging step,
# and then updates omni.ja in place. If you're not using Eclipse, you
# should be using |mach build mobile/android && mach package|.
$(abspath $(DIST)/fennec/$(OMNIJAR_NAME)): FORCE
$(REPORT_BUILD)
$(MAKE) -C ../locales
$(MAKE) -C ../chrome
$(MAKE) -C ../components
$(MAKE) -C ../modules
$(MAKE) -C ../app
$(MAKE) -C ../themes/core
$(MAKE) -C ../installer stage-package
rsync --update $(DIST)/fennec/$(notdir $(OMNIJAR_NAME)) $@
$(RM) $(DIST)/fennec/$(notdir $(OMNIJAR_NAME))
libs:: geckoview_resources.zip classes.dex jni-stubs.inc GeneratedJNIWrappers.cpp fennec_ids.txt
$(INSTALL) geckoview_resources.zip $(FINAL_TARGET)
$(INSTALL) classes.dex $(FINAL_TARGET)

View File

@ -1,17 +0,0 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#filter substitution
package @ANDROID_PACKAGE_NAME@;
/**
* Declare a predefined number of Webapp<num> classes to the Webapps class.
* These are used so that each web app can launch in its own process. Keep this
* number in sync with the number of web apps handled in WebappAllocator.
*/
public final class WebApps {
#define FRAGMENT WebappsFragment.java.frag
#include WebappFragmentRepeater.inc
}

View File

@ -3,8 +3,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#filter substitution
package @ANDROID_PACKAGE_NAME@;
package org.mozilla.gecko;
import org.mozilla.gecko.webapp.WebappImpl;

View File

@ -1,4 +1,4 @@
<activity android:name=".WebApps$WebApp@APPNUM@"
<activity android:name="org.mozilla.gecko.webapp.Webapps$Webapp@APPNUM@"
android:label="@string/webapp_generic_name"
android:configChanges="keyboard|keyboardHidden|mcc|mnc|orientation|screenSize"
android:windowSoftInputMode="stateUnspecified|adjustResize"

View File

@ -1,5 +0,0 @@
public static class WebApp@APPNUM@ extends Webapp {
@Override
protected int getIndex() { return @APPNUM@; }
}

View File

@ -27,8 +27,8 @@ public class GlobalConstants {
public static final String MOZ_APP_DISPLAYNAME = "@MOZ_APP_DISPLAYNAME@";
public static final String MOZ_APP_VERSION = "@MOZ_APP_VERSION@";
public static final String BROWSER_INTENT_PACKAGE = "@ANDROID_PACKAGE_NAME@";
public static final String BROWSER_INTENT_CLASS = BROWSER_INTENT_PACKAGE + ".App";
public static final String BROWSER_INTENT_PACKAGE = "org.mozilla.gecko";
public static final String BROWSER_INTENT_CLASS = BROWSER_INTENT_PACKAGE + ".BrowserApp";
/**
* Bug 800244: this signing-level permission protects broadcast intents that

View File

@ -288,7 +288,8 @@ class BookmarksListAdapter extends MultiTypeCursorAdapter {
} else {
final BookmarkFolderView row = (BookmarkFolderView) view;
if (cursor == null) {
row.setText(mParentStack.peek().title);
final Resources res = context.getResources();
row.setText(res.getString(R.string.home_move_up_to_filter, mParentStack.get(1).title));
row.open();
} else {
row.setText(getFolderTitle(context, cursor));

View File

@ -17,6 +17,7 @@ import org.mozilla.gecko.home.HomePager.OnUrlOpenListener;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.Configuration;
import android.database.Cursor;
import android.os.Bundle;
@ -188,7 +189,11 @@ public class BookmarksPanel extends HomeFragment {
private final RefreshType mRefreshType;
public BookmarksLoader(Context context) {
this(context, new FolderInfo(Bookmarks.FIXED_ROOT_ID), RefreshType.CHILD);
super(context);
final Resources res = context.getResources();
final String title = res.getString(R.string.bookmarks_title);
mFolderInfo = new FolderInfo(Bookmarks.FIXED_ROOT_ID, title);
mRefreshType = RefreshType.CHILD;
}
public BookmarksLoader(Context context, FolderInfo folderInfo, RefreshType refreshType) {

View File

@ -402,6 +402,7 @@ gbjar.sources += [
'updater/UpdateService.java',
'updater/UpdateServiceHelper.java',
'VideoPlayer.java',
'Webapp.java',
'webapp/Allocator.java',
'webapp/ApkResources.java',
'webapp/Dispatcher.java',
@ -411,6 +412,7 @@ gbjar.sources += [
'webapp/TaskKiller.java',
'webapp/UninstallListener.java',
'webapp/WebappImpl.java',
'webapp/Webapps.java',
'widget/ActivityChooserModel.java',
'widget/AllCapsTextView.java',
'widget/AnimatedHeightLayout.java',
@ -444,13 +446,6 @@ gbjar.sources += [ thirdparty_source_dir + f for f in [
'com/googlecode/eyesfree/braille/selfbraille/WriteData.java',
] ]
android_package_dir = CONFIG['ANDROID_PACKAGE_NAME'].replace('.', '/')
# All generated sources are handled specially in Makefile.in. And
# R.java is handled even more specially than the others!
gbjar.generated_sources += [ android_package_dir + f for f in [
'/App.java',
'/Webapp.java',
'/WebApps.java',
] ]
gbjar.generated_sources += [
'org/mozilla/gecko/AppConstants.java',
'org/mozilla/gecko/SysInfo.java',
@ -581,10 +576,9 @@ main.filtered_resources += [
]
main.recursive_make_targets += generated_recursive_make_targets
main.recursive_make_targets += [OBJDIR + '/generated/' + f for f in mgjar.generated_sources]
main.recursive_make_targets += [OBJDIR + '/generated/' + f for f in gbjar.generated_sources]
main.recursive_make_targets += ['generated/' + f for f in mgjar.generated_sources]
main.recursive_make_targets += ['generated/' + f for f in gbjar.generated_sources]
main.included_projects += ['../' + generated.name, '../' + branding.name]
main.extra_jars += [CONFIG['ANDROID_COMPAT_LIB']]
main.assets = TOPOBJDIR + '/dist/' + CONFIG['MOZ_APP_NAME'] + '/assets'
main.libs = TOPOBJDIR + '/dist/' + CONFIG['MOZ_APP_NAME'] + '/lib'
@ -608,8 +602,23 @@ resources.res = SRCDIR + '/resources'
resources.included_projects += ['../' + generated.name, '../' + branding.name]
resources.recursive_make_targets += generated_recursive_make_targets
# The resources are included in the Fennec APK.
main.included_projects += ['../' + resources.name]
main.referenced_projects += [resources.name]
omnijar = add_android_eclipse_library_project('FennecOmnijar')
omnijar.package_name = 'org.mozilla.fennec.omnijar'
# This is delicate. We write into OBJDIR, and write triggers a new build of the
# Fennec project, because the omni.ja timestamp is always updated. (The target
# is FORCE and the installer does not track dependencies.) However, Eclipse only
# triggers a new build (of FennecOmnijar) when something actually changes, so
# we're not constantly rebuilding the FennecOmnijar (or Fennec) project.
omnijar.recursive_make_targets += [TOPOBJDIR + '/dist/fennec/assets/omni.ja']
for d in ['app', 'chrome', 'components', 'locales', 'modules', 'themes']:
omnijar.add_classpathentry(d, TOPSRCDIR + '/mobile/android/' + d, dstdir=d)
# The omnijar is included in the Fennec APK (although it's empty,
# having no resources, assets, or Java code).
main.included_projects += [omnijar.name]
if CONFIG['MOZ_CRASHREPORTER']:
crashreporter = add_android_eclipse_library_project('FennecResourcesCrashReporter')

Binary file not shown.

Before

Width:  |  Height:  |  Size: 491 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 374 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 560 B

View File

@ -8,7 +8,7 @@
<!-- state open -->
<item gecko:state_open="true"
android:drawable="@drawable/bookmark_folder_opened"/>
android:drawable="@drawable/folder_up"/>
<!-- state close -->
<item android:drawable="@drawable/bookmark_folder_closed"/>

View File

@ -12,6 +12,8 @@ import org.mozilla.gecko.FennecMochitestAssert;
import org.mozilla.gecko.FennecNativeDriver;
import org.mozilla.gecko.FennecTalosAssert;
import org.mozilla.gecko.AppConstants;
import android.app.Activity;
import android.test.ActivityInstrumentationTestCase2;
import android.util.Log;
@ -24,6 +26,25 @@ public abstract class BaseRobocopTest extends ActivityInstrumentationTestCase2<A
private static final String DEFAULT_ROOT_PATH = "/mnt/sdcard/tests";
/**
* The Java Class instance that launches the browser.
* <p>
* This should always agree with {@link AppConstants#BROWSER_INTENT_CLASS_NAME}.
*/
public static final Class<? extends Activity> BROWSER_INTENT_CLASS;
// Use reflection here so we don't have to preprocess this file.
static {
Class<? extends Activity> cl;
try {
cl = (Class<? extends Activity>) Class.forName(AppConstants.BROWSER_INTENT_CLASS_NAME);
} catch (ClassNotFoundException e) {
// Oh well.
cl = Activity.class;
}
BROWSER_INTENT_CLASS = cl;
}
protected Assert mAsserter;
protected String mLogFile;
@ -41,7 +62,7 @@ public abstract class BaseRobocopTest extends ActivityInstrumentationTestCase2<A
*/
@SuppressWarnings("unchecked")
public BaseRobocopTest() {
this((Class<Activity>) TestConstants.BROWSER_INTENT_CLASS);
this((Class<Activity>) BROWSER_INTENT_CLASS);
}
/**

View File

@ -149,6 +149,8 @@ public class StringHelper {
public static final String TABS_FROM_LAST_TIME_LABEL = "Open all tabs from last time";
// Desktop default bookmarks folders
public static final String BOOKMARKS_UP_TO = "Up to %s";
public static final String BOOKMARKS_ROOT_LABEL = "Bookmarks";
public static final String DESKTOP_FOLDER_LABEL = "Desktop Bookmarks";
public static final String TOOLBAR_FOLDER_LABEL = "Bookmarks Toolbar";
public static final String BOOKMARKS_MENU_FOLDER_LABEL = "Bookmarks Menu";

View File

@ -1,18 +0,0 @@
#filter substitution
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.tests;
import android.app.Activity;
public class TestConstants {
/**
* The Java Class instance that launches the browser.
* <p>
* This should always agree with {@link AppConstants#BROWSER_INTENT_CLASS_NAME}.
*/
public static final Class<? extends Activity> BROWSER_INTENT_CLASS = @ANDROID_PACKAGE_NAME@.App.class;
}

View File

@ -40,10 +40,10 @@ public class testBookmarkFolders extends AboutHomeTest {
clickOnBookmarkFolder(StringHelper.TOOLBAR_FOLDER_LABEL);
// Go up in the bookmark folder hierarchy
clickOnBookmarkFolder(StringHelper.TOOLBAR_FOLDER_LABEL);
clickOnBookmarkFolder(String.format(StringHelper.BOOKMARKS_UP_TO, StringHelper.DESKTOP_FOLDER_LABEL));
mAsserter.ok(waitForText(StringHelper.BOOKMARKS_MENU_FOLDER_LABEL), "Going up in the folder hierarchy", "We are back in the Desktop Bookmarks folder");
clickOnBookmarkFolder(StringHelper.DESKTOP_FOLDER_LABEL);
clickOnBookmarkFolder(String.format(StringHelper.BOOKMARKS_UP_TO, StringHelper.BOOKMARKS_ROOT_LABEL));
mAsserter.ok(waitForText(StringHelper.DESKTOP_FOLDER_LABEL), "Going up in the folder hierarchy", "We are back in the main Bookmarks List View");
clickOnBookmarkFolder(StringHelper.DESKTOP_FOLDER_LABEL);
@ -74,7 +74,7 @@ public class testBookmarkFolders extends AboutHomeTest {
mAsserter.ok(!waitForText(contextMenuString), "Folders do not have context menus", "The context menu was not opened");
// Even if no context menu is opened long clicking a folder still opens it. We need to close it.
clickOnBookmarkFolder(StringHelper.DESKTOP_FOLDER_LABEL);
clickOnBookmarkFolder(String.format(StringHelper.BOOKMARKS_UP_TO, StringHelper.BOOKMARKS_ROOT_LABEL));
}
private void clickOnBookmarkFolder(final String folderName) {

View File

@ -108,6 +108,13 @@ public final class WebActivityMapper {
public String getAction() {
return Intent.ACTION_GET_CONTENT;
}
@Override
public String getMime(JSONObject data) throws JSONException {
// bug 1007112 - pick action needs a mimetype to work
String mime = data.optString("type", null);
return !TextUtils.isEmpty(mime) ? mime : "*/*";
}
}
private static class SendMapping extends BaseMapping {

View File

@ -44,8 +44,8 @@ public class Dispatcher extends Activity {
// Copy the intent, without interfering with it.
Intent intent = new Intent(getIntent());
// Only change it's destination.
intent.setClassName(getApplicationContext(), getPackageName() + ".WebApps$WebApp" + index);
// Only change its destination.
intent.setClassName(getApplicationContext(), "org.mozilla.gecko.webapp.Webapps$Webapp" + index);
// If and only if we haven't seen this before.
intent.putExtra("isInstalled", isInstalled);

View File

@ -32,6 +32,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.util.Log;
public class EventListener implements NativeEventListener {
@ -142,9 +143,9 @@ public class EventListener implements NativeEventListener {
final JSONObject messageData;
// We get the manifest url out of javascript here so we can use it as a checksum
// in a minute, when a package has been installed.
String manifestUrl = null;
String filePath = null;
// in InstallListener when a package has been installed.
String manifestUrl;
String filePath;
try {
filePath = message.getString("filePath");
@ -156,43 +157,48 @@ public class EventListener implements NativeEventListener {
return;
}
// We will check the manifestUrl from the one in the APK.
// Thus, we can have a one-to-one mapping of apk to receiver.
final InstallListener receiver = new InstallListener(manifestUrl, messageData);
final File file = new File(filePath);
// Listen for packages being installed.
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
filter.addDataScheme("package");
context.registerReceiver(receiver, filter);
File file = new File(filePath);
if (!file.exists()) {
Log.wtf(LOGTAG, "APK file doesn't exist at path " + filePath);
callback.sendError("APK file doesn't exist at path " + filePath);
return;
}
// We will check the manifestUrl from the one in the APK.
// Thus, we can have a one-to-one mapping of apk to receiver.
final InstallListener receiver = new InstallListener(manifestUrl, messageData, file);
// Listen for packages being installed.
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
filter.addDataScheme("package");
// As of API 19 we can do something like this to only trigger this receiver
// for a specific package name:
// int currentApiVersion = android.os.Build.VERSION.SDK_INT;
// if (currentApiVersion >= android.os.Build.VERSION_CODES.KITKAT){ // KITKAT == 19
// filter.addDataSchemeSpecificPart("com.example.someapp", PatternMatcher.PATTERN_LITERAL);
// }
// TODO: Implement package name filtering to IntentFilter.
context.registerReceiver(receiver, filter);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
// Now call the package installer.
ActivityHandlerHelper.startIntentForActivity(context, intent, new ActivityResultHandler() {
// Invoked if the user cancels installation or presses the 'Done'
// button once the app has been successfully installed. It may also
// be called when the user presses Open and then returns to Fennec.
@Override
public void onActivityResult(int resultCode, Intent data) {
// The InstallListener will catch the case where the user pressed install.
// Now deal with if the user pressed cancel.
if (resultCode == Activity.RESULT_CANCELED) {
try {
context.unregisterReceiver(receiver);
receiver.cleanup();
} catch (java.lang.IllegalArgumentException e) {
// IllegalArgumentException happens because resultCode is RESULT_CANCELED
// when the user presses the Done button in the install confirmation dialog,
// even though the install has been successful (and InstallListener already
// unregistered the receiver).
Log.e(LOGTAG, "error unregistering install receiver: ", e);
}
if (!receiver.isReceived()) {
callback.sendError("APK installation cancelled by user");
context.unregisterReceiver(receiver);
}
if (file.delete()) {
Log.i(LOGTAG, "Downloaded APK file deleted");
}
}
});

View File

@ -16,7 +16,6 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;
@ -25,11 +24,19 @@ public class InstallListener extends BroadcastReceiver {
private static String LOGTAG = "GeckoWebappInstallListener";
private JSONObject mData = null;
private String mManifestUrl;
private boolean mReceived = false;
private File mApkFile;
public InstallListener(String manifestUrl, JSONObject data) {
public InstallListener(String manifestUrl, JSONObject data, File apkFile) {
mData = data;
mApkFile = apkFile;
mManifestUrl = manifestUrl;
assert mManifestUrl != null;
assert mApkFile != null && mApkFile.exists();
}
public boolean isReceived() {
return mReceived;
}
@Override
@ -61,6 +68,15 @@ public class InstallListener extends BroadcastReceiver {
return;
}
// If we're here then everything is looking good and installation can continue.
mReceived = true;
context.unregisterReceiver(this);
if (mApkFile != null && mApkFile.delete()) {
Log.i(LOGTAG, "Downloaded APK file deleted");
}
if (GeckoThread.checkLaunchState(GeckoThread.LaunchState.GeckoRunning)) {
InstallHelper installHelper = new InstallHelper(context, apkResources, null);
try {
@ -76,11 +92,6 @@ public class InstallListener extends BroadcastReceiver {
Log.e(LOGTAG, "Couldn't install packaged app", e);
}
}
cleanup();
// we don't need this anymore.
context.unregisterReceiver(this);
}
public boolean isCorrectManifest(String manifestUrl) {
@ -96,13 +107,4 @@ public class InstallListener extends BroadcastReceiver {
return false;
}
public void cleanup() {
String manifestUrlFilename = mManifestUrl.replaceAll("[^a-zA-Z0-9]", "");
File apkFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), manifestUrlFilename + ".apk");
if (apkFile.exists()) {
apkFile.delete();
Log.i(LOGTAG, "Downloaded APK file deleted");
}
}
}

View File

@ -0,0 +1,513 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.webapp;
/**
* Declare a predefined number of Webapp<num> classes to the Webapps class.
* These are used so that each web app can launch in its own process. Keep this
* number in sync with the number of web apps defined in the Android manifest.
*/
public final class Webapps {
public static class Webapp0 extends WebappImpl {
@Override
protected int getIndex() { return 0; }
}
public static class Webapp1 extends WebappImpl {
@Override
protected int getIndex() { return 1; }
}
public static class Webapp2 extends WebappImpl {
@Override
protected int getIndex() { return 2; }
}
public static class Webapp3 extends WebappImpl {
@Override
protected int getIndex() { return 3; }
}
public static class Webapp4 extends WebappImpl {
@Override
protected int getIndex() { return 4; }
}
public static class Webapp5 extends WebappImpl {
@Override
protected int getIndex() { return 5; }
}
public static class Webapp6 extends WebappImpl {
@Override
protected int getIndex() { return 6; }
}
public static class Webapp7 extends WebappImpl {
@Override
protected int getIndex() { return 7; }
}
public static class Webapp8 extends WebappImpl {
@Override
protected int getIndex() { return 8; }
}
public static class Webapp9 extends WebappImpl {
@Override
protected int getIndex() { return 9; }
}
public static class Webapp10 extends WebappImpl {
@Override
protected int getIndex() { return 10; }
}
public static class Webapp11 extends WebappImpl {
@Override
protected int getIndex() { return 11; }
}
public static class Webapp12 extends WebappImpl {
@Override
protected int getIndex() { return 12; }
}
public static class Webapp13 extends WebappImpl {
@Override
protected int getIndex() { return 13; }
}
public static class Webapp14 extends WebappImpl {
@Override
protected int getIndex() { return 14; }
}
public static class Webapp15 extends WebappImpl {
@Override
protected int getIndex() { return 15; }
}
public static class Webapp16 extends WebappImpl {
@Override
protected int getIndex() { return 16; }
}
public static class Webapp17 extends WebappImpl {
@Override
protected int getIndex() { return 17; }
}
public static class Webapp18 extends WebappImpl {
@Override
protected int getIndex() { return 18; }
}
public static class Webapp19 extends WebappImpl {
@Override
protected int getIndex() { return 19; }
}
public static class Webapp20 extends WebappImpl {
@Override
protected int getIndex() { return 20; }
}
public static class Webapp21 extends WebappImpl {
@Override
protected int getIndex() { return 21; }
}
public static class Webapp22 extends WebappImpl {
@Override
protected int getIndex() { return 22; }
}
public static class Webapp23 extends WebappImpl {
@Override
protected int getIndex() { return 23; }
}
public static class Webapp24 extends WebappImpl {
@Override
protected int getIndex() { return 24; }
}
public static class Webapp25 extends WebappImpl {
@Override
protected int getIndex() { return 25; }
}
public static class Webapp26 extends WebappImpl {
@Override
protected int getIndex() { return 26; }
}
public static class Webapp27 extends WebappImpl {
@Override
protected int getIndex() { return 27; }
}
public static class Webapp28 extends WebappImpl {
@Override
protected int getIndex() { return 28; }
}
public static class Webapp29 extends WebappImpl {
@Override
protected int getIndex() { return 29; }
}
public static class Webapp30 extends WebappImpl {
@Override
protected int getIndex() { return 30; }
}
public static class Webapp31 extends WebappImpl {
@Override
protected int getIndex() { return 31; }
}
public static class Webapp32 extends WebappImpl {
@Override
protected int getIndex() { return 32; }
}
public static class Webapp33 extends WebappImpl {
@Override
protected int getIndex() { return 33; }
}
public static class Webapp34 extends WebappImpl {
@Override
protected int getIndex() { return 34; }
}
public static class Webapp35 extends WebappImpl {
@Override
protected int getIndex() { return 35; }
}
public static class Webapp36 extends WebappImpl {
@Override
protected int getIndex() { return 36; }
}
public static class Webapp37 extends WebappImpl {
@Override
protected int getIndex() { return 37; }
}
public static class Webapp38 extends WebappImpl {
@Override
protected int getIndex() { return 38; }
}
public static class Webapp39 extends WebappImpl {
@Override
protected int getIndex() { return 39; }
}
public static class Webapp40 extends WebappImpl {
@Override
protected int getIndex() { return 40; }
}
public static class Webapp41 extends WebappImpl {
@Override
protected int getIndex() { return 41; }
}
public static class Webapp42 extends WebappImpl {
@Override
protected int getIndex() { return 42; }
}
public static class Webapp43 extends WebappImpl {
@Override
protected int getIndex() { return 43; }
}
public static class Webapp44 extends WebappImpl {
@Override
protected int getIndex() { return 44; }
}
public static class Webapp45 extends WebappImpl {
@Override
protected int getIndex() { return 45; }
}
public static class Webapp46 extends WebappImpl {
@Override
protected int getIndex() { return 46; }
}
public static class Webapp47 extends WebappImpl {
@Override
protected int getIndex() { return 47; }
}
public static class Webapp48 extends WebappImpl {
@Override
protected int getIndex() { return 48; }
}
public static class Webapp49 extends WebappImpl {
@Override
protected int getIndex() { return 49; }
}
public static class Webapp50 extends WebappImpl {
@Override
protected int getIndex() { return 50; }
}
public static class Webapp51 extends WebappImpl {
@Override
protected int getIndex() { return 51; }
}
public static class Webapp52 extends WebappImpl {
@Override
protected int getIndex() { return 52; }
}
public static class Webapp53 extends WebappImpl {
@Override
protected int getIndex() { return 53; }
}
public static class Webapp54 extends WebappImpl {
@Override
protected int getIndex() { return 54; }
}
public static class Webapp55 extends WebappImpl {
@Override
protected int getIndex() { return 55; }
}
public static class Webapp56 extends WebappImpl {
@Override
protected int getIndex() { return 56; }
}
public static class Webapp57 extends WebappImpl {
@Override
protected int getIndex() { return 57; }
}
public static class Webapp58 extends WebappImpl {
@Override
protected int getIndex() { return 58; }
}
public static class Webapp59 extends WebappImpl {
@Override
protected int getIndex() { return 59; }
}
public static class Webapp60 extends WebappImpl {
@Override
protected int getIndex() { return 60; }
}
public static class Webapp61 extends WebappImpl {
@Override
protected int getIndex() { return 61; }
}
public static class Webapp62 extends WebappImpl {
@Override
protected int getIndex() { return 62; }
}
public static class Webapp63 extends WebappImpl {
@Override
protected int getIndex() { return 63; }
}
public static class Webapp64 extends WebappImpl {
@Override
protected int getIndex() { return 64; }
}
public static class Webapp65 extends WebappImpl {
@Override
protected int getIndex() { return 65; }
}
public static class Webapp66 extends WebappImpl {
@Override
protected int getIndex() { return 66; }
}
public static class Webapp67 extends WebappImpl {
@Override
protected int getIndex() { return 67; }
}
public static class Webapp68 extends WebappImpl {
@Override
protected int getIndex() { return 68; }
}
public static class Webapp69 extends WebappImpl {
@Override
protected int getIndex() { return 69; }
}
public static class Webapp70 extends WebappImpl {
@Override
protected int getIndex() { return 70; }
}
public static class Webapp71 extends WebappImpl {
@Override
protected int getIndex() { return 71; }
}
public static class Webapp72 extends WebappImpl {
@Override
protected int getIndex() { return 72; }
}
public static class Webapp73 extends WebappImpl {
@Override
protected int getIndex() { return 73; }
}
public static class Webapp74 extends WebappImpl {
@Override
protected int getIndex() { return 74; }
}
public static class Webapp75 extends WebappImpl {
@Override
protected int getIndex() { return 75; }
}
public static class Webapp76 extends WebappImpl {
@Override
protected int getIndex() { return 76; }
}
public static class Webapp77 extends WebappImpl {
@Override
protected int getIndex() { return 77; }
}
public static class Webapp78 extends WebappImpl {
@Override
protected int getIndex() { return 78; }
}
public static class Webapp79 extends WebappImpl {
@Override
protected int getIndex() { return 79; }
}
public static class Webapp80 extends WebappImpl {
@Override
protected int getIndex() { return 80; }
}
public static class Webapp81 extends WebappImpl {
@Override
protected int getIndex() { return 81; }
}
public static class Webapp82 extends WebappImpl {
@Override
protected int getIndex() { return 82; }
}
public static class Webapp83 extends WebappImpl {
@Override
protected int getIndex() { return 83; }
}
public static class Webapp84 extends WebappImpl {
@Override
protected int getIndex() { return 84; }
}
public static class Webapp85 extends WebappImpl {
@Override
protected int getIndex() { return 85; }
}
public static class Webapp86 extends WebappImpl {
@Override
protected int getIndex() { return 86; }
}
public static class Webapp87 extends WebappImpl {
@Override
protected int getIndex() { return 87; }
}
public static class Webapp88 extends WebappImpl {
@Override
protected int getIndex() { return 88; }
}
public static class Webapp89 extends WebappImpl {
@Override
protected int getIndex() { return 89; }
}
public static class Webapp90 extends WebappImpl {
@Override
protected int getIndex() { return 90; }
}
public static class Webapp91 extends WebappImpl {
@Override
protected int getIndex() { return 91; }
}
public static class Webapp92 extends WebappImpl {
@Override
protected int getIndex() { return 92; }
}
public static class Webapp93 extends WebappImpl {
@Override
protected int getIndex() { return 93; }
}
public static class Webapp94 extends WebappImpl {
@Override
protected int getIndex() { return 94; }
}
public static class Webapp95 extends WebappImpl {
@Override
protected int getIndex() { return 95; }
}
public static class Webapp96 extends WebappImpl {
@Override
protected int getIndex() { return 96; }
}
public static class Webapp97 extends WebappImpl {
@Override
protected int getIndex() { return 97; }
}
public static class Webapp98 extends WebappImpl {
@Override
protected int getIndex() { return 98; }
}
public static class Webapp99 extends WebappImpl {
@Override
protected int getIndex() { return 99; }
}
}

View File

@ -1,18 +0,0 @@
#filter substitution
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ant.AntBuilderLaunchConfigurationType">
<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_CLEAN_TARGETS" value="post_build,"/>
<booleanAttribute key="org.eclipse.ant.ui.ATTR_TARGETS_UPDATED" value="true"/>
<booleanAttribute key="org.eclipse.ant.ui.DEFAULT_VM_INSTALL" value="false"/>
<booleanAttribute key="org.eclipse.debug.core.capture_output" value="true"/>
<booleanAttribute key="org.eclipse.debug.ui.ATTR_CONSOLE_OUTPUT_ON" value="true"/>
<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${project}"/>
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.ant.ui.AntClasspathProvider"/>
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="true"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="@IDE_PROJECT_NAME@"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/@IDE_PROJECT_NAME@/post_build.xml}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="clean"/>
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-Dbuild_type=&quot;${build_type}&quot;&#10;-Dbuild_files=&quot;DUMMY ${build_files}&quot;"/>
</launchConfiguration>

View File

@ -1,19 +0,0 @@
#filter substitution
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ant.AntBuilderLaunchConfigurationType">
<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_AUTO_TARGETS" value="pre_build,"/>
<stringAttribute key="org.eclipse.ant.ui.ATTR_ANT_MANUAL_TARGETS" value="pre_build,"/>
<booleanAttribute key="org.eclipse.ant.ui.ATTR_TARGETS_UPDATED" value="true"/>
<booleanAttribute key="org.eclipse.ant.ui.DEFAULT_VM_INSTALL" value="false"/>
<booleanAttribute key="org.eclipse.debug.core.capture_output" value="true"/>
<booleanAttribute key="org.eclipse.debug.ui.ATTR_CONSOLE_OUTPUT_ON" value="true"/>
<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${project}"/>
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.ant.ui.AntClasspathProvider"/>
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="true"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="@IDE_PROJECT_NAME@"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/@IDE_PROJECT_NAME@/pre_build.xml}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="incremental,auto"/>
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-Dbuild_type=&quot;${build_type}&quot;&#10;-Dbuild_files=&quot;DUMMY ${build_files}&quot;"/>
</launchConfiguration>

View File

@ -7,11 +7,15 @@
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<name>org.mozilla.ide.eclipse.fennec.FennecMakeBuilder</name>
<arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/PreBuilder.launch</value>
<key>command</key>
<value>@IDE_TOPSRCDIR@/mach build @IDE_OBJDIR@/ANDROID_ECLIPSE_PROJECT_@IDE_PROJECT_NAME@</value>
</dictionary>
<dictionary>
<key>workingDirectory</key>
<value>@IDE_TOPOBJDIR@</value>
</dictionary>
</arguments>
</buildCommand>
@ -35,15 +39,6 @@
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/PostBuilder.launch</value>
</dictionary>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.android.ide.eclipse.adt.AndroidNature</nature>

View File

@ -1,45 +0,0 @@
#filter substitution
<?xml version="1.0" encoding="UTF-8"?>
<project>
<property name="topsrcdir" value="@IDE_TOPSRCDIR@"/>
<property name="topobjdir" value="@IDE_TOPOBJDIR@"/>
<property name="objdir" value="@IDE_OBJDIR@"/>
<property name="project_name" value="@IDE_PROJECT_NAME@"/>
<!-- This file can get large (!), but for a short time we want to
log as much information for debugging build loops as possible. -->
<record name="${topobjdir}/android_eclipse/build.log" append="yes" />
<target name="build_needed" >
<script language="javascript" >
<![CDATA[
importClass(java.io.File);
var build_files = project.getProperty("build_files").split(" ");
var after = [];
var echo = project.createTask("echo");
var info = Packages.org.apache.tools.ant.taskdefs.Echo.EchoLevel();
info.setValue("info");
echo.setLevel(info);
// Timestamp.
echo.addText(project.getProperty("project_name") + " build type " + project.getProperty("build_type") + " started at: " + new Date());
echo.addText(project.getProperty("line.separator"));
echo.perform();
// The if below checks for the property being defined, not its value.
project.setProperty("build_needed", build_needed);
]]>
</script>
</target>
<target name="post_build" depends="build_needed" if="build_needed">
<exec executable="${topsrcdir}/mach" dir="${topobjdir}" failonerror="true">
<arg value="build"/>
<arg value="${objdir}/ANDROID_ECLIPSE_PROJECT_${project_name}"/>
</exec>
</target>
</project>

View File

@ -1,79 +0,0 @@
#filter substitution
<?xml version="1.0" encoding="UTF-8"?>
<project>
<property name="topsrcdir" value="@IDE_TOPSRCDIR@"/>
<property name="topobjdir" value="@IDE_TOPOBJDIR@"/>
<property name="objdir" value="@IDE_OBJDIR@"/>
<property name="project_name" value="@IDE_PROJECT_NAME@"/>
<!-- This file can get large (!), but for a short time we want to
log as much information for debugging build loops as possible. -->
<record name="${topobjdir}/android_eclipse/build.log" append="yes" />
<target name="build_needed" >
<script language="javascript" >
<![CDATA[
importClass(java.io.File);
var build_files = project.getProperty("build_files").split(" ");
var after = [];
var echo = project.createTask("echo");
var info = Packages.org.apache.tools.ant.taskdefs.Echo.EchoLevel();
info.setValue("info");
echo.setLevel(info);
// Timestamp.
echo.addText(project.getProperty("project_name") + " build type " + project.getProperty("build_type") + " started at: " + new Date());
echo.addText(project.getProperty("line.separator"));
var build_needed = false;
// Skip leading DUMMY.
for (var i = 1; i < build_files.length; i++) {
build_file = build_files[i];
build_file_needed = true;
if ((new File(build_file)).isDirectory()) {
build_file_needed = false;
}
var rel = build_file.split(project.getBaseDir(), 2)[1];
if (rel && (rel.startsWith("/bin/") || rel.startsWith("/gen/") || rel.endsWith(".class"))) {
build_file_needed = false;
}
if (build_file_needed) {
echo.addText("1 ");
} else {
echo.addText("0 ");
}
echo.addText(build_file);
echo.addText(project.getProperty("line.separator"));
build_needed |= build_file_needed;
}
echo.addText(project.getProperty("project_name") + " build type " + project.getProperty("build_type") + " checked at: " + new Date());
if (build_needed) {
echo.addText(" requires updating");
} else {
echo.addText(" does not require updating");
}
echo.addText(project.getProperty("line.separator"));
echo.perform();
// The if below checks for the property being defined, not its value.
if (build_needed) {
project.setProperty("build_needed", build_needed);
}
]]>
</script>
</target>
<target name="pre_build" depends="build_needed" if="build_needed">
<exec executable="${topsrcdir}/mach" dir="${topobjdir}" failonerror="true">
<arg value="build"/>
<arg value="${objdir}/ANDROID_ECLIPSE_PROJECT_${project_name}"/>
</exec>
</target>
</project>

View File

@ -44,11 +44,8 @@ class TestAndroidEclipseBackend(BackendTester):
"""Ensure we generate reasonable files for main (non-library) projects."""
self.env = self._consume('android_eclipse', AndroidEclipseBackend)
for f in ['.classpath',
'.externalToolBuilders',
'.project',
'.settings',
'pre_build.xml',
'post_build.xml',
'gen',
'lint.xml',
'project.properties']:

View File

@ -297,8 +297,18 @@
readonly="true"/>
<property name="messageManager"
onget="return this.QueryInterface(Components.interfaces.nsIFrameLoaderOwner).frameLoader.messageManager;"
readonly="true"/>
readonly="true">
<getter>
<![CDATA[
var owner = this.QueryInterface(Components.interfaces.nsIFrameLoaderOwner);
if (!owner.frameLoader) {
return null;
}
return owner.frameLoader.messageManager;
]]>
</getter>
</property>
<field name="_webNavigation">null</field>

View File

@ -1578,8 +1578,7 @@ ThreadActor.prototype = {
if (!actualLocation) {
actualLocation = {
url: aLocation.url,
line: line,
column: 0
line: line
};
}
found = true;
@ -5175,6 +5174,8 @@ ThreadSources.prototype = {
*/
getOriginalLocation: function ({ url, line, column }) {
if (url in this._sourceMapsByGeneratedSource) {
column = column || 0;
return this._sourceMapsByGeneratedSource[url]
.then((aSourceMap) => {
let { source: aSourceURL, line: aLine, column: aColumn } = aSourceMap.originalPositionFor({

View File

@ -424,7 +424,7 @@ static void mergeNativeBacktrace(ThreadProfile &aProfile, const PCArray &array)
while (pseudoStackPos < stack->stackSize()) {
volatile StackEntry& entry = stack->mStack[pseudoStackPos];
if (entry.stackAddress() < array.sp_array[i-1] && entry.stackAddress())
if (entry.isCpp() && entry.stackAddress() && entry.stackAddress() < array.sp_array[i-1])
break;
addProfileEntry(entry, aProfile, stack, array.array[0]);