Merge f-t to m-c

This commit is contained in:
Phil Ringnalda 2014-03-17 22:42:42 -07:00
commit a742504b73
21 changed files with 207 additions and 368 deletions

View File

@ -232,6 +232,7 @@ support-files =
[browser_dbg_variables-view-accessibility.js]
[browser_dbg_variables-view-data.js]
[browser_dbg_variables-view-edit-cancel.js]
[browser_dbg_variables-view-edit-click.js]
[browser_dbg_variables-view-edit-getset-01.js]
[browser_dbg_variables-view-edit-getset-02.js]
[browser_dbg_variables-view-edit-value.js]

View File

@ -0,0 +1,52 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Check that the editing state of a Variable is correctly tracked. Clicking on
* the textbox while editing should not cancel editing.
*/
const TAB_URL = EXAMPLE_URL + "doc_watch-expressions.html";
function test() {
Task.spawn(function*() {
let [tab, debuggee, panel] = yield initDebugger(TAB_URL);
let win = panel.panelWin;
let vars = win.DebuggerView.Variables;
win.DebuggerView.WatchExpressions.addExpression("this");
// Allow this generator function to yield first.
executeSoon(() => debuggee.ermahgerd());
yield waitForDebuggerEvents(panel, win.EVENTS.FETCHED_WATCH_EXPRESSIONS);
let exprScope = vars.getScopeAtIndex(0);
let exprVar = exprScope.get("this");
let name = exprVar.target.querySelector(".title > .name");
is(exprVar.editing, false,
"The expression should indicate it is not being edited.");
EventUtils.sendMouseEvent({ type: "dblclick" }, name, win);
let input = exprVar.target.querySelector(".title > .element-name-input");
is(exprVar.editing, true,
"The expression should indicate it is being edited.");
is(input.selectionStart !== input.selectionEnd, true,
"The expression text should be selected.");
EventUtils.synthesizeMouse(input, 2, 2, {}, win);
is(exprVar.editing, true,
"The expression should indicate it is still being edited after a click.");
is(input.selectionStart === input.selectionEnd, true,
"The expression text should not be selected.");
EventUtils.sendKey("ESCAPE", win);
is(exprVar.editing, false,
"The expression should indicate it is not being edited after cancelling.");
// Why is this needed?
EventUtils.synthesizeMouse(vars.parentNode, 2, 2, {}, win);
yield resumeDebuggerThenCloseAndFinish(panel);
});
}

View File

@ -1830,7 +1830,8 @@ Scope.prototype = {
* The click listener for this scope's title.
*/
_onClick: function(e) {
if (e.button != 0 ||
if (this.editing ||
e.button != 0 ||
e.target == this._editNode ||
e.target == this._deleteNode ||
e.target == this._addPropertyNode) {
@ -2081,6 +2082,7 @@ Scope.prototype = {
new: null,
preventDisableOnChange: false,
preventDescriptorModifiers: false,
editing: false,
editableNameTooltip: "",
editableValueTooltip: "",
editButtonTooltip: "",
@ -3889,6 +3891,7 @@ Editable.prototype = {
this._variable.collapse();
this._variable.hideArrow();
this._variable.locked = true;
this._variable.editing = true;
},
/**
@ -3906,6 +3909,7 @@ Editable.prototype = {
this._variable.locked = false;
this._variable.twisty = this._prevExpandable;
this._variable.expanded = this._prevExpanded;
this._variable.editing = false;
this._onCleanup && this._onCleanup();
},

View File

@ -162,8 +162,6 @@ toolbarbutton.chevron:-moz-locale-dir(rtl) > .toolbarbutton-icon {
toolbarbutton.bookmark-item:not(.subviewbutton):not(#bookmarks-menu-button),
#personal-bookmarks[cui-areatype="toolbar"]:not([overflowedItem=true]) > #bookmarks-toolbar-placeholder {
font-weight: bold;
color: #222;
border: 0;
border-radius: 10000px;
padding: 1px 8px;

Binary file not shown.

After

Width:  |  Height:  |  Size: 528 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 689 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 380 B

View File

@ -0,0 +1 @@
blassey@flyingfox.local.319

View File

@ -4,20 +4,13 @@
package org.mozilla.gecko.sync;
import org.mozilla.gecko.background.common.log.Logger;
import android.content.ContentResolver;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
public class PrefsBackoffHandler implements BackoffHandler {
private static final String LOG_TAG = "BackoffHandler";
public static final String PREF_EARLIEST_NEXT = "earliestnext";
private final SharedPreferences prefs;
private final String prefSuffix;
private final String prefEarliest;
public PrefsBackoffHandler(final SharedPreferences prefs, final String prefSuffix) {
@ -25,7 +18,6 @@ public class PrefsBackoffHandler implements BackoffHandler {
throw new IllegalArgumentException("prefs must not be null.");
}
this.prefs = prefs;
this.prefSuffix = prefSuffix;
this.prefEarliest = PREF_EARLIEST_NEXT + "." + prefSuffix;
}

View File

@ -4,7 +4,6 @@
package org.mozilla.gecko.sync.setup.activities;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

View File

@ -1,3 +1,4 @@
// -*- Mode: js2; tab-width: 2; indent-tabs-mode: nil; js2-basic-offset: 2; js2-skip-preprocessor-directives: t; -*-
/* 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/. */
@ -275,6 +276,42 @@ var SelectionHandler = {
return false;
}
if (this._isPhoneNumber(selection.toString())) {
let anchorNode = selection.anchorNode;
let anchorOffset = selection.anchorOffset;
let focusNode = null;
let focusOffset = null;
while (this._isPhoneNumber(selection.toString().trim())) {
focusNode = selection.focusNode;
focusOffset = selection.focusOffset;
selection.modify("extend", "forward", "word");
// if we hit the end of the text on the page, we can't advance the selection
if (focusNode == selection.focusNode && focusOffset == selection.focusOffset) {
break;
}
}
// reverse selection
selection.collapse(focusNode, focusOffset);
selection.extend(anchorNode, anchorOffset);
anchorNode = focusNode;
anchorOffset = focusOffset
while (this._isPhoneNumber(selection.toString().trim())) {
focusNode = selection.focusNode;
focusOffset = selection.focusOffset;
selection.modify("extend", "backward", "word");
// if we hit the end of the text on the page, we can't advance the selection
if (focusNode == selection.focusNode && focusOffset == selection.focusOffset) {
break;
}
}
selection.collapse(focusNode, focusOffset);
selection.extend(anchorNode, anchorOffset);
}
// Add a listener to end the selection if it's removed programatically
selection.QueryInterface(Ci.nsISelectionPrivate).addSelectionListener(this);
this._activeType = this.TYPE_SELECTION;
@ -494,6 +531,20 @@ var SelectionHandler = {
selector: ClipboardHelper.searchWithContext,
},
CALL: {
label: Strings.browser.GetStringFromName("contextmenu.call"),
id: "call_action",
icon: "drawable://phone",
action: function() {
SelectionHandler.callSelection();
},
order: 1,
selector: {
matches: function isPhoneNumber(aElement, aX, aY) {
return null != SelectionHandler._getSelectedPhoneNumber();
}
},
},
},
/*
@ -744,6 +795,24 @@ var SelectionHandler = {
this._closeSelection();
},
_phoneRegex: /^\+?[0-9\s,-.\(\)*#pw]{1,30}$/,
_getSelectedPhoneNumber: function sh_getSelectedPhoneNumber() {
return this._isPhoneNumber(this._getSelectedText().trim());
},
_isPhoneNumber: function sh_isPhoneNumber(selectedText) {
return (this._phoneRegex.test(selectedText) ? selectedText : null);
},
callSelection: function sh_callSelection() {
let selectedText = this._getSelectedPhoneNumber();
if (selectedText) {
BrowserApp.loadURI("tel:" + selectedText);
}
this._closeSelection();
},
/*
* Shuts SelectionHandler down.
*/
@ -904,6 +973,7 @@ var SelectionHandler = {
positions: positions,
rtl: this._isRTL
});
this._updateMenu();
},
subdocumentScrolled: function sh_subdocumentScrolled(aElement) {

View File

@ -201,6 +201,8 @@ contextmenu.cut=Cut
contextmenu.selectAll=Select All
contextmenu.paste=Paste
contextmenu.call=Call
# Select UI
selectHelper.closeMultipleSelectDialog=Done

View File

@ -246,9 +246,7 @@ this.DebuggerClient = function (aTransport)
this._activeRequests = new Map;
this._eventsEnabled = true;
this.compat = new ProtocolCompatibility(this, [
new SourcesShim(),
]);
this.compat = new ProtocolCompatibility(this, []);
this.traits = {};
this.request = this.request.bind(this);
@ -932,41 +930,6 @@ const FeatureCompatibilityShim = {
}
};
/**
* A shim to support the "sources" and "newSource" packets for older servers
* which don't support them.
*/
function SourcesShim() {
this._sourcesSeen = new Set();
}
SourcesShim.prototype = Object.create(FeatureCompatibilityShim);
let SSProto = SourcesShim.prototype;
SSProto.name = "sources";
SSProto.onPacketTest = function (aPacket) {
if (aPacket.traits) {
return aPacket.traits.sources
? SUPPORTED
: NOT_SUPPORTED;
}
return SKIP;
};
SSProto.translatePacket = function (aPacket, aReplacePacket, aExtraPacket,
aKeepPacket) {
if (aPacket.type !== "newScript" || this._sourcesSeen.has(aPacket.url)) {
return aKeepPacket();
}
this._sourcesSeen.add(aPacket.url);
return aExtraPacket({
from: aPacket.from,
type: "newSource",
source: aPacket.source
});
};
/**
* Creates a tab client for the remote debugging protocol server. This client
* is a front to the tab actor created in the server side, hiding the protocol
@ -1526,52 +1489,11 @@ ThreadClient.prototype = {
* @param aOnResponse Function
* Called with the thread's response.
*/
getSources: function (aOnResponse) {
// This is how we should get sources if the server supports "sources"
// requests.
let getSources = DebuggerClient.requester({
type: "sources"
}, {
telemetry: "SOURCES"
});
// This is how we should deduct what sources exist from the existing scripts
// when the server does not support "sources" requests.
let getSourcesBackwardsCompat = DebuggerClient.requester({
type: "scripts"
}, {
after: function (aResponse) {
if (aResponse.error) {
return aResponse;
}
let sourceActorsByURL = aResponse.scripts
.reduce(function (aSourceActorsByURL, aScript) {
aSourceActorsByURL[aScript.url] = aScript.source;
return aSourceActorsByURL;
}, {});
return {
sources: [
{ url: url, actor: sourceActorsByURL[url] }
for (url of Object.keys(sourceActorsByURL))
]
}
},
telemetry: "SOURCES"
});
// On the first time `getSources` is called, patch the thread client with
// the best method for the server's capabilities.
let threadClient = this;
this.compat.supportsFeature("sources").then(function () {
threadClient.getSources = getSources;
}, function () {
threadClient.getSources = getSourcesBackwardsCompat;
}).then(function () {
threadClient.getSources(aOnResponse);
});
},
getSources: DebuggerClient.requester({
type: "sources"
}, {
telemetry: "SOURCES"
}),
_doInterrupted: function (aAction, aError) {
if (this.paused) {

View File

@ -488,19 +488,42 @@
}
/**
* Make sure that we put "\n" into the output instead of actual newlines.
* Make sure that we output the escaped character combination inside string literals
* instead of various problematic characters.
*/
function sanitizeNewlines(str) {
return str.replace(/\n/g, "\\n");
}
var sanitize = (function () {
var escapeCharacters = {
// Backslash
"\\": "\\\\",
// Newlines
"\n": "\\n",
// Carriage return
"\r": "\\r",
// Tab
"\t": "\\t",
// Vertical tab
"\v": "\\v",
// Form feed
"\f": "\\f",
// Null character
"\0": "\\0",
// Single quotes
"'": "\\'"
};
/**
* Make sure that we put "\'" into the single-quoted output instead of raw single quotes.
*/
function sanitizeSingleQuotes(str) {
return str.replace(/\'/g, "\\'");
}
var regExpString = "("
+ Object.keys(escapeCharacters)
.map(function (c) { return escapeCharacters[c]; })
.join("|")
+ ")";
var escapeCharactersRegExp = new RegExp(regExpString, "g");
return function(str) {
return str.replace(escapeCharactersRegExp, function (_, c) {
return escapeCharacters[c];
});
}
}());
/**
* Add the given token to the pretty printed results.
*
@ -513,7 +536,7 @@
*/
function addToken(token, write, options) {
if (token.type.type == "string") {
write("'" + sanitizeSingleQuotes(sanitizeNewlines(token.value)) + "'",
write("'" + sanitize(token.value) + "'",
token.startLoc.line,
token.startLoc.column);
} else {

View File

@ -445,6 +445,42 @@ var testCases = [
"}\n"
},
{
name: "Escaping backslashes in strings",
input: "'\\\\'\n",
output: "'\\\\'\n"
},
{
name: "Escaping carriage return in strings",
input: "'\\r'\n",
output: "'\\r'\n"
},
{
name: "Escaping tab in strings",
input: "'\\t'\n",
output: "'\\t'\n"
},
{
name: "Escaping vertical tab in strings",
input: "'\\v'\n",
output: "'\\v'\n"
},
{
name: "Escaping form feed in strings",
input: "'\\f'\n",
output: "'\\f'\n"
},
{
name: "Escaping null character in strings",
input: "'\\0'\n",
output: "'\\0'\n"
},
];
var sourceMap = this.sourceMap || require("source-map");

View File

@ -195,15 +195,6 @@ function initTestTracerServer()
DebuggerServer.init(function () { return true; });
}
function initSourcesBackwardsCompatDebuggerServer()
{
DebuggerServer.addActors("resource://gre/modules/devtools/server/actors/root.js");
DebuggerServer.addActors("resource://gre/modules/devtools/server/actors/webbrowser.js");
DebuggerServer.addActors("resource://gre/modules/devtools/server/actors/script.js");
DebuggerServer.addActors("resource://test/testcompatactors.js");
DebuggerServer.init(function () { return true; });
}
function finishClient(aClient)
{
aClient.close(function() {

View File

@ -44,9 +44,6 @@ function test_source()
gThreadClient.getSources(function (aResponse) {
do_check_true(!!aResponse);
do_check_true(!!aResponse.sources);
gClient.compat.supportsFeature("sources").then(function (supported) {
do_check_true(supported);
});
let source = aResponse.sources.filter(function (s) {
return s.url === SOURCE_URL;

View File

@ -1,77 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Check that "sources" and "newSource" packets are handled in a backwards
* compatible way.
*/
var gDebuggee;
var gClient;
var gTabClient;
var gThreadClient;
var gNumTimesSourcesSent = 0;
function run_test()
{
initSourcesBackwardsCompatDebuggerServer();
gDebuggee = addTestGlobal("test-sources-compat");
gClient = new DebuggerClient(DebuggerServer.connectPipe());
gClient.request = (function (request) {
return function (aRequest, aOnResponse) {
if (aRequest.type === "sources") {
++gNumTimesSourcesSent;
}
return request.call(this, aRequest, aOnResponse);
};
}(gClient.request));
gClient.connect(function() {
attachTestTabAndResume(gClient, "test-sources-compat", function (aResponse,
aTabClient,
aThreadClient) {
gTabClient = aTabClient;
gThreadClient = aThreadClient;
test_new_source_compatibility();
});
});
do_test_pending();
}
function test_new_source_compatibility()
{
gClient.addOneTimeListener("newSource", function (aEvent, aPacket) {
do_check_eq(aEvent, "newSource");
do_check_eq(aPacket.type, "newSource");
do_check_true(!!aPacket.source);
do_check_true(
!!aPacket.source.url.match(/test_sources_backwards_compat-01.js$/));
gClient.compat.supportsFeature("sources").then(function () {
do_check_true(
false,
"The server shouldn't support sources since we mocked it not to.");
}, test_sources_compatibility);
});
gDebuggee.eval(function inc(n) {
return n+1;
}.toString());
}
function test_sources_compatibility()
{
gThreadClient.getSources(function (aResponse) {
do_check_true(!aResponse.error);
do_check_true(aResponse.sources.some(function (s) {
return s.url.match(/test_sources_backwards_compat-01.js$/);
}));
do_check_true(gNumTimesSourcesSent <= 1,
"Should only send one sources request at most, even though we"
+ " might have had to send one to determine feature support.");
finishClient(gClient);
});
}

View File

@ -1,51 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Check getting sources before there are any, in backwards compatibility mode.
*/
var gDebuggee;
var gClient;
var gTabClient;
var gThreadClient;
var gNumTimesSourcesSent = 0;
function run_test()
{
initSourcesBackwardsCompatDebuggerServer();
gDebuggee = addTestGlobal("test-sources-compat");
gClient = new DebuggerClient(DebuggerServer.connectPipe());
gClient.request = (function (request) {
return function (aRequest, aOnResponse) {
if (aRequest.type === "sources") {
++gNumTimesSourcesSent;
}
return request.call(this, aRequest, aOnResponse);
};
}(gClient.request));
gClient.connect(function() {
attachTestTabAndResume(gClient, "test-sources-compat", function (aResponse,
aTabClient,
aThreadClient) {
gTabClient = aTabClient;
gThreadClient = aThreadClient;
test_listing_zero_sources_compat();
});
});
do_test_pending();
}
function test_listing_zero_sources_compat()
{
gThreadClient.getSources(function (aPacket) {
do_check_true(!aPacket.error);
do_check_true(!!aPacket.sources);
do_check_eq(aPacket.sources.length, 0);
do_check_true(gNumTimesSourcesSent <= 1,
"Should only send one sources request, even though we might "
+ "have had to send one to determine feature support.");
finishClient(gClient);
});
}

View File

@ -1,118 +0,0 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
var gTestGlobals = [];
function createRootActor()
{
let actor = {
sayHello: function() {
this._tabActors = [];
for each (let g in gTestGlobals) {
let actor = new BrowserTabActor(this.conn);
actor.thread = new ThreadActor({}, g);
actor.json = function() {
return { actor: actor.actorID,
url: "http://www.example.com/",
title: actor.thread.global.__name };
};
actor.requestTypes["attach"] = function (aRequest) {
dump("actor.thread.actorID = " + actor.thread.actorID + "\n");
return {
from: actor.actorID,
type: "tabAttached",
threadActor: actor.thread.actorID
};
};
actor.thread.requestTypes["scripts"] = function (aRequest) {
return this._discoverSources().then(function () {
let scripts = [];
for (let s of this.dbg.findScripts()) {
if (!s.url) {
continue;
}
let script = {
url: s.url,
startLine: s.startLine,
lineCount: s.lineCount,
source: this.sources.source({ url: s.url }).form()
};
scripts.push(script);
}
return {
from: this.actorID,
scripts: scripts
};
}.bind(this));
};
// Pretend that we do not know about the "sources" packet to force the
// client to go into its backwards compatibility mode.
actor.thread.requestTypes["sources"] = function () {
return {
error: "unrecognizedPacketType"
};
};
let { conn } = this;
actor.thread.onNewScript = (function (oldOnNewScript) {
return function (aScript) {
oldOnNewScript.call(this, aScript);
conn.send({
from: actor.thread.actorID,
type: "newScript",
url: aScript.url,
startLine: aScript.startLine,
lineCount: aScript.lineCount,
source: actor.thread.sources.source({ url: aScript.url }).form()
});
};
}(actor.thread.onNewScript));
this.conn.addActor(actor);
this.conn.addActor(actor.thread);
this._tabActors.push(actor);
}
this.conn.send = (function (aOldSend) {
return function (aPacket) {
if (aPacket.type === "newSource") {
// Don't send newSource Packets b/c we are an old version of the
// RDP!
return undefined;
} else {
return aOldSend.call(this, aPacket);
}
};
}(this.conn.send));
return { from: "root",
applicationType: "xpcshell-tests",
traits: {} };
},
listTabs: function(aRequest) {
return {
from: "root",
selected: 0,
tabs: [ actor.json() for (actor of this._tabActors) ]
};
},
};
actor.requestTypes = {
"listTabs": actor.listTabs,
"echo": function(aRequest) { return aRequest; },
};
return actor;
}
DebuggerServer.addTestGlobal = function addTestGlobal(aGlobal)
{
aGlobal.wrappedJSObject = aGlobal;
gTestGlobals.push(aGlobal);
}

View File

@ -13,7 +13,6 @@ support-files =
registertestactors-02.js
sourcemapped.js
testactors.js
testcompatactors.js
tracerlocations.js
[test_nesting-01.js]
@ -119,8 +118,6 @@ run-if = toolkit == "gonk"
[test_listsources-02.js]
[test_listsources-03.js]
[test_new_source-01.js]
[test_sources_backwards_compat-01.js]
[test_sources_backwards_compat-02.js]
[test_sourcemaps-01.js]
[test_sourcemaps-02.js]
[test_sourcemaps-03.js]