Merge fx-team to m-c. a=merge

This commit is contained in:
Ryan VanderMeulen 2015-04-15 21:23:40 -04:00
commit 66f788b23d
12 changed files with 167 additions and 104 deletions

View File

@ -944,6 +944,7 @@ var gBrowserInit = {
LanguageDetectionListener.init();
BrowserOnClick.init();
DevEdition.init();
AboutPrivateBrowsingListener.init();
let mm = window.getGroupMessageManager("browsers");
mm.loadFrameScript("chrome://browser/content/tab-content.js", true);
@ -7784,3 +7785,13 @@ let PanicButtonNotifier = {
popup.hidePopup();
},
};
let AboutPrivateBrowsingListener = {
init: function () {
window.messageManager.addMessageListener(
"AboutPrivateBrowsing:OpenPrivateWindow",
msg => {
OpenBrowserWindow({private: true});
});
}
};

View File

@ -264,6 +264,29 @@ let AboutHomeListener = {
};
AboutHomeListener.init(this);
let AboutPrivateBrowsingListener = {
init(chromeGlobal) {
chromeGlobal.addEventListener("AboutPrivateBrowsingOpenWindow", this,
false, true);
},
get isAboutPrivateBrowsing() {
return content.document.documentURI.toLowerCase() == "about:privatebrowsing";
},
handleEvent(aEvent) {
if (!this.isAboutPrivateBrowsing) {
return;
}
switch (aEvent.type) {
case "AboutPrivateBrowsingOpenWindow":
sendAsyncMessage("AboutPrivateBrowsing:OpenPrivateWindow");
break;
}
},
};
AboutPrivateBrowsingListener.init(this);
let AboutReaderListener = {
_articlePromise: null,

View File

@ -7,24 +7,17 @@
* opened one time when in private browsing.
*/
function test() {
waitForExplicitFinish();
var win = OpenBrowserWindow({private: true});
add_task(function* test() {
let win = yield BrowserTestUtils.openNewBrowserWindow({private: true});
whenDelayedStartupFinished(win, function() {
win.gBrowser.loadURI("about:addons");
let tab = win.gBrowser.selectedTab = win.gBrowser.addTab("about:addons");
yield BrowserTestUtils.browserLoaded(tab.linkedBrowser);
yield promiseWaitForFocus(win);
waitForFocus(function() {
EventUtils.synthesizeKey("a", { ctrlKey: true, shiftKey: true }, win);
is(win.gBrowser.tabs.length, 1, "about:addons tab was re-focused.");
is(win.gBrowser.currentURI.spec, "about:addons", "Addons tab was opened.");
win.close();
finish();
});
});
}
EventUtils.synthesizeKey("a", { ctrlKey: true, shiftKey: true }, win);
is(win.gBrowser.tabs.length, 2, "about:addons tab was re-focused.");
is(win.gBrowser.currentURI.spec, "about:addons", "Addons tab was opened.");
yield BrowserTestUtils.closeWindow(win);
});

View File

@ -61,6 +61,7 @@ static RedirEntry kRedirMap[] = {
nsIAboutModule::ALLOW_SCRIPT |
nsIAboutModule::HIDE_FROM_ABOUTABOUT },
{ "privatebrowsing", "chrome://browser/content/aboutPrivateBrowsing.xhtml",
nsIAboutModule::URI_MUST_LOAD_IN_CHILD |
nsIAboutModule::ALLOW_SCRIPT },
{ "rights",
#ifdef MOZ_OFFICIAL_BRANDING

View File

@ -17,13 +17,6 @@ if (!PrivateBrowsingUtils.isContentWindowPrivate(window)) {
setFavIcon("chrome://browser/skin/Privacy-16.png");
}
var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem)
.rootTreeItem
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow);
function setFavIcon(url) {
var icon = document.createElement("link");
icon.setAttribute("rel", "icon");
@ -54,5 +47,7 @@ document.addEventListener("DOMContentLoaded", function () {
}, false);
function openPrivateWindow() {
mainWindow.OpenBrowserWindow({private: true});
// Ask chrome to open a private window
document.dispatchEvent(
new CustomEvent("AboutPrivateBrowsingOpenWindow", {bubbles:true}));
}

View File

@ -48,8 +48,6 @@ function test() {
function testDownloadDir(aWin, gDownloadLastDir, aFile, aDisplayDir, aLastDir,
aGlobalLastDir, aCallback) {
let context = aWin.gBrowser.selectedBrowser.contentWindow;
// Check lastDir preference.
is(prefs.getComplexValue("lastDir", Ci.nsIFile).path, aDisplayDir.path,
"LastDir should be the expected display dir");
@ -78,7 +76,7 @@ function test() {
aCallback();
};
launcherDialog.promptForSaveToFileAsync(launcher, context, null, null, null);
launcherDialog.promptForSaveToFileAsync(launcher, aWin, null, null, null);
}
testOnWindow(false, function(win, downloadDir) {

View File

@ -1396,9 +1396,6 @@ public abstract class GeckoApp
mLayerView = layerView;
GeckoAppShell.sendEventToGecko(GeckoEvent.createObjectEvent(
GeckoEvent.ACTION_OBJECT_LAYER_CLIENT, layerView.getLayerClientObject()));
// bind the GeckoEditable instance to the new LayerView
GeckoAppShell.notifyIMEContext(GeckoEditableListener.IME_STATE_DISABLED, "", "", "");
}
}

View File

@ -321,8 +321,17 @@ public class GeckoAppShell
return;
}
sLayerView = lv;
// Install new Gecko-to-Java editable listener.
editableListener = new GeckoEditable();
// We should have a unique GeckoEditable instance per nsWindow instance,
// so even though we have a new view here, the underlying nsWindow is the same,
// and we don't create a new GeckoEditable.
if (editableListener == null) {
// Starting up; istall new Gecko-to-Java editable listener.
editableListener = new GeckoEditable();
} else {
// Bind the existing GeckoEditable instance to the new LayerView
GeckoAppShell.notifyIMEContext(GeckoEditableListener.IME_STATE_DISABLED, "", "", "");
}
}
@RobocopTarget

View File

@ -729,6 +729,46 @@ final class GeckoEditable
}
}
private void notifyCommitComposition() {
// Gecko already committed its composition, and
// we should remove the composition on our side as well.
boolean wasComposing = false;
final Object[] spans = mText.getSpans(0, mText.length(), Object.class);
for (Object span : spans) {
if ((mText.getSpanFlags(span) & Spanned.SPAN_COMPOSING) != 0) {
mText.removeSpan(span);
wasComposing = true;
}
}
if (!wasComposing) {
return;
}
// Generate a text change notification if we actually cleared the composition.
final CharSequence text = TextUtils.stringOrSpannedString(mText);
geckoPostToIc(new Runnable() {
@Override
public void run() {
mListener.onTextChange(text, 0, text.length(), text.length());
}
});
}
private void notifyCancelComposition() {
// Composition should have been cancelled on our side
// through text update notifications; verify that here.
if (DEBUG) {
final Object[] spans = mText.getSpans(0, mText.length(), Object.class);
for (Object span : spans) {
if ((mText.getSpanFlags(span) & Spanned.SPAN_COMPOSING) != 0) {
throw new IllegalStateException("composition not cancelled");
}
}
}
}
@Override
public void notifyIME(final int type) {
if (DEBUG) {
@ -741,6 +781,7 @@ final class GeckoEditable
")");
}
}
if (type == NOTIFY_IME_REPLY_EVENT) {
try {
if (mGeckoFocused) {
@ -756,7 +797,14 @@ final class GeckoEditable
mActionQueue.poll();
}
return;
} else if (type == NOTIFY_IME_TO_COMMIT_COMPOSITION) {
notifyCommitComposition();
return;
} else if (type == NOTIFY_IME_TO_CANCEL_COMPOSITION) {
notifyCancelComposition();
return;
}
geckoPostToIc(new Runnable() {
@Override
public void run() {
@ -909,6 +957,7 @@ final class GeckoEditable
throw new IllegalArgumentException("newEnd does not match text");
}
final int newEnd = start + text.length();
final Action action = mActionQueue.peek();
/* Text changes affect the selection as well, and we may not receive another selection
update as a result of selection notification masking on the Gecko side; therefore,
@ -916,55 +965,60 @@ final class GeckoEditable
to increment the seqno here as well */
++mGeckoUpdateSeqno;
mChangedText.clearSpans();
mChangedText.replace(0, mChangedText.length(), text);
// Preserve as many spans as possible
TextUtils.copySpansFrom(mText, start, Math.min(oldEnd, newEnd),
Object.class, mChangedText, 0);
final Action action = mActionQueue.peek();
if (action != null &&
(action.mType == Action.TYPE_REPLACE_TEXT ||
action.mType == Action.TYPE_COMPOSE_TEXT) &&
start <= action.mStart &&
action.mStart + action.mSequence.length() <= newEnd) {
// actionNewEnd is the new end of the original replacement action
final int actionNewEnd = action.mStart + action.mSequence.length();
int selStart = Selection.getSelectionStart(mText);
int selEnd = Selection.getSelectionEnd(mText);
// Replace old spans with new spans
mChangedText.replace(action.mStart - start, actionNewEnd - start,
action.mSequence);
geckoReplaceText(start, oldEnd, mChangedText);
// delete/insert above might have moved our selection to somewhere else
// this happens when the Gecko text change covers a larger range than
// the original replacement action. Fix selection here
if (selStart >= start && selStart <= oldEnd) {
selStart = selStart < action.mStart ? selStart :
selStart < action.mEnd ? actionNewEnd :
selStart + actionNewEnd - action.mEnd;
mText.setSpan(Selection.SELECTION_START, selStart, selStart,
Spanned.SPAN_POINT_POINT);
}
if (selEnd >= start && selEnd <= oldEnd) {
selEnd = selEnd < action.mStart ? selEnd :
selEnd < action.mEnd ? actionNewEnd :
selEnd + actionNewEnd - action.mEnd;
mText.setSpan(Selection.SELECTION_END, selEnd, selEnd,
Spanned.SPAN_POINT_POINT);
}
if (action != null && action.mType == Action.TYPE_ACKNOWLEDGE_FOCUS) {
// Simply replace the text for newly-focused editors.
mText.replace(0, mText.length(), text);
} else {
// Gecko side initiated the text change.
if (isSameText(start, oldEnd, mChangedText)) {
// Nothing to do because the text is the same.
// This could happen when the composition is updated for example.
return;
mChangedText.clearSpans();
mChangedText.replace(0, mChangedText.length(), text);
// Preserve as many spans as possible
TextUtils.copySpansFrom(mText, start, Math.min(oldEnd, newEnd),
Object.class, mChangedText, 0);
if (action != null &&
(action.mType == Action.TYPE_REPLACE_TEXT ||
action.mType == Action.TYPE_COMPOSE_TEXT) &&
start <= action.mStart &&
action.mStart + action.mSequence.length() <= newEnd) {
// actionNewEnd is the new end of the original replacement action
final int actionNewEnd = action.mStart + action.mSequence.length();
int selStart = Selection.getSelectionStart(mText);
int selEnd = Selection.getSelectionEnd(mText);
// Replace old spans with new spans
mChangedText.replace(action.mStart - start, actionNewEnd - start,
action.mSequence);
geckoReplaceText(start, oldEnd, mChangedText);
// delete/insert above might have moved our selection to somewhere else
// this happens when the Gecko text change covers a larger range than
// the original replacement action. Fix selection here
if (selStart >= start && selStart <= oldEnd) {
selStart = selStart < action.mStart ? selStart :
selStart < action.mEnd ? actionNewEnd :
selStart + actionNewEnd - action.mEnd;
mText.setSpan(Selection.SELECTION_START, selStart, selStart,
Spanned.SPAN_POINT_POINT);
}
if (selEnd >= start && selEnd <= oldEnd) {
selEnd = selEnd < action.mStart ? selEnd :
selEnd < action.mEnd ? actionNewEnd :
selEnd + actionNewEnd - action.mEnd;
mText.setSpan(Selection.SELECTION_END, selEnd, selEnd,
Spanned.SPAN_POINT_POINT);
}
} else {
// Gecko side initiated the text change.
if (isSameText(start, oldEnd, mChangedText)) {
// Nothing to do because the text is the same.
// This could happen when the composition is updated for example.
return;
}
geckoReplaceText(start, oldEnd, mChangedText);
}
geckoReplaceText(start, oldEnd, mChangedText);
}
geckoPostToIc(new Runnable() {

View File

@ -227,7 +227,6 @@ class GeckoInputConnection
private final ExtractedText mUpdateExtract = new ExtractedText();
private boolean mBatchSelectionChanged;
private boolean mBatchTextChanged;
private long mLastRestartInputTime;
private final InputConnection mKeyInputConnection;
public static GeckoEditableListener create(View targetView,
@ -383,19 +382,8 @@ class GeckoInputConnection
}
}
private void tryRestartInput() {
// Coalesce restartInput calls because InputMethodManager.restartInput()
// is expensive and successive calls to it can lock up the keyboard
if (SystemClock.uptimeMillis() < mLastRestartInputTime + 200) {
return;
}
restartInput();
}
private void restartInput() {
mLastRestartInputTime = SystemClock.uptimeMillis();
final InputMethodManager imm = getInputMethodManager();
if (imm == null) {
return;
@ -916,17 +904,6 @@ class GeckoInputConnection
public void notifyIME(int type) {
switch (type) {
case NOTIFY_IME_TO_CANCEL_COMPOSITION:
// Set composition to empty and end composition
setComposingText("", 0);
// Fall through
case NOTIFY_IME_TO_COMMIT_COMPOSITION:
// Commit and end composition
finishComposingText();
tryRestartInput();
break;
case NOTIFY_IME_OF_FOCUS:
case NOTIFY_IME_OF_BLUR:
// Showing/hiding vkb is done in notifyIMEContext

View File

@ -229,7 +229,12 @@ public class LocalReadingListStorage implements ReadingListStorage {
@Override
public void addDownloadedRecord(ServerReadingListRecord down) {
additionsOrChanges.add(down);
final Boolean deleted = down.fields.getBoolean("deleted");
if (deleted != null && deleted.booleanValue()) {
addDeletion(down.getGUID());
} else {
additionsOrChanges.add(down);
}
}
}

View File

@ -23,7 +23,7 @@ public abstract class ReadingListRecord {
* From server record.
*/
public ServerMetadata(ExtendedJSONObject obj) {
this(obj.getString("id"), obj.getLong("last_modified"));
this(obj.getString("id"), obj.containsKey("last_modified") ? obj.getLong("last_modified") : -1L);
}
}