Bug 1367081 - Make PromptService usable from GeckoView custom tabs; r=droeh

Make PromptService and Prompt.jsm not depend as much on BrowserApp and
the main Fennec window, so it can be used from a GeckoView-based custom
tabs Activity. This approach is used because it involves a lot less work
than trying to implement a PromptDelegate for Fennec.

MozReview-Commit-ID: AEH0HgAOx2S
This commit is contained in:
Jim Chen 2017-06-01 15:07:16 -04:00
Родитель c83f61bb2b
Коммит 6b1641fe89
3 изменённых файлов: 38 добавлений и 14 удалений

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

@ -1841,7 +1841,7 @@ public abstract class GeckoApp extends GeckoActivity
startActivity(settingsIntent); startActivity(settingsIntent);
} }
mPromptService = new PromptService(this); mPromptService = new PromptService(this, getAppEventDispatcher());
// Trigger the completion of the telemetry timer that wraps activity startup, // Trigger the completion of the telemetry timer that wraps activity startup,
// then grab the duration to give to FHR. // then grab the duration to give to FHR.

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

@ -6,8 +6,6 @@
package org.mozilla.gecko.prompts; package org.mozilla.gecko.prompts;
import org.mozilla.gecko.EventDispatcher; import org.mozilla.gecko.EventDispatcher;
import org.mozilla.gecko.GeckoApp;
import org.mozilla.gecko.GeckoAppShell;
import org.mozilla.gecko.util.BundleEventListener; import org.mozilla.gecko.util.BundleEventListener;
import org.mozilla.gecko.util.EventCallback; import org.mozilla.gecko.util.EventCallback;
import org.mozilla.gecko.util.GeckoBundle; import org.mozilla.gecko.util.GeckoBundle;
@ -19,17 +17,19 @@ import android.util.Log;
public class PromptService implements BundleEventListener { public class PromptService implements BundleEventListener {
private static final String LOGTAG = "GeckoPromptService"; private static final String LOGTAG = "GeckoPromptService";
private final GeckoApp mGeckoApp; private final Context mContext;
private final EventDispatcher mDispatcher;
public PromptService(GeckoApp geckoApp) { public PromptService(final Context context, final EventDispatcher dispatcher) {
mGeckoApp = geckoApp; mContext = context;
mGeckoApp.getAppEventDispatcher().registerUiThreadListener(this, mDispatcher = dispatcher;
mDispatcher.registerUiThreadListener(this,
"Prompt:Show", "Prompt:Show",
"Prompt:ShowTop"); "Prompt:ShowTop");
} }
public void destroy() { public void destroy() {
mGeckoApp.getAppEventDispatcher().unregisterUiThreadListener(this, mDispatcher.unregisterUiThreadListener(this,
"Prompt:Show", "Prompt:Show",
"Prompt:ShowTop"); "Prompt:ShowTop");
} }
@ -39,7 +39,7 @@ public class PromptService implements BundleEventListener {
public void handleMessage(final String event, final GeckoBundle message, public void handleMessage(final String event, final GeckoBundle message,
final EventCallback callback) { final EventCallback callback) {
Prompt p; Prompt p;
p = new Prompt(mGeckoApp, new Prompt.PromptCallback() { p = new Prompt(mContext, new Prompt.PromptCallback() {
@Override @Override
public void onPromptFinished(final GeckoBundle result) { public void onPromptFinished(final GeckoBundle result) {
callback.sendSuccess(result); callback.sendSuccess(result);

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

@ -7,6 +7,7 @@
var Cc = Components.classes; var Cc = Components.classes;
var Ci = Components.interfaces; var Ci = Components.interfaces;
Components.utils.import("resource://gre/modules/Messaging.jsm");
Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://gre/modules/Services.jsm");
this.EXPORTED_SYMBOLS = ["Prompt"]; this.EXPORTED_SYMBOLS = ["Prompt"];
@ -15,14 +16,24 @@ function log(msg) {
Services.console.logStringMessage(msg); Services.console.logStringMessage(msg);
} }
function getRootWindow(win) {
// Get the root xul window.
return win.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDocShell).QueryInterface(Ci.nsIDocShellTreeItem)
.rootTreeItem.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow);
}
function Prompt(aOptions) { function Prompt(aOptions) {
this.window = "window" in aOptions ? aOptions.window : null; this.window = "window" in aOptions ? aOptions.window : null;
this.msg = { async: true }; this.msg = { async: true };
if (this.window) { if (this.window) {
let window = Services.wm.getMostRecentWindow("navigator:browser"); let window = getRootWindow(this.window);
var tab = window.BrowserApp.getTabForWindow(this.window); var tab = window &&
window.BrowserApp &&
window.BrowserApp.getTabForWindow(this.window);
if (tab) { if (tab) {
this.msg.tabId = tab.id; this.msg.tabId = tab.id;
} }
@ -174,11 +185,24 @@ Prompt.prototype = {
this._innerShow(); this._innerShow();
}, },
_getDispatcher: function(win) {
let root = win && getRootWindow(win);
try {
return root && (root.WindowEventDispatcher || EventDispatcher.for(root));
} catch (e) {
// No EventDispatcher for this window.
return null;
}
},
_innerShow: function() { _innerShow: function() {
let window = Services.wm.getMostRecentWindow("navigator:browser"); let dispatcher =
window.WindowEventDispatcher.sendRequestForResult(this.msg).then((data) => { this._getDispatcher(this.window) ||
if (this.callback) this._getDispatcher(Services.wm.getMostRecentWindow("navigator:browser"));
dispatcher.sendRequestForResult(this.msg).then((data) => {
if (this.callback) {
this.callback(data); this.callback(data);
}
}); });
}, },