mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge fx-team to m-c. a=merge
This commit is contained in:
commit
66f788b23d
@ -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});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
});
|
||||
|
@ -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
|
||||
|
@ -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}));
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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, "", "", "");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user