diff --git a/mobile/android/base/moz.build b/mobile/android/base/moz.build index 50eb75d7b356..773cfd390bac 100644 --- a/mobile/android/base/moz.build +++ b/mobile/android/base/moz.build @@ -258,7 +258,6 @@ gvjar.sources += [geckoview_source_dir + 'java/org/mozilla/gecko/' + x 'GeckoThread.java', 'GeckoView.java', 'GeckoViewChrome.java', - 'GeckoViewContent.java', 'GeckoViewFragment.java', 'gfx/BitmapUtils.java', 'gfx/BufferedImage.java', diff --git a/mobile/android/chrome/content/GeckoViewContent.js b/mobile/android/chrome/content/GeckoViewContent.js new file mode 100644 index 000000000000..78f935f28586 --- /dev/null +++ b/mobile/android/chrome/content/GeckoViewContent.js @@ -0,0 +1,41 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* 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/. */ + +var { classes: Cc, interfaces: Ci, utils: Cu } = Components; + +var dump = Cu.import("resource://gre/modules/AndroidLog.jsm", {}).AndroidLog.d.bind(null, "ViewContent"); + +var DEBUG = false; + +// This is copied from desktop's tab-content.js. See bug 1153485 about sharing this code somehow. +var DOMTitleChangedListener = { + init: function() { + addEventListener("DOMTitleChanged", this, false); + }, + + receiveMessage: function(message) { + if (DEBUG) { + dump("receiveMessage " + message.name); + } + }, + + handleEvent: function(aEvent) { + if (aEvent.originalTarget.defaultView != content) { + return; + } + + if (DEBUG) { + dump("handleEvent " + aEvent.type); + } + + switch (aEvent.type) { + case "DOMTitleChanged": + sendAsyncMessage("GeckoView:DOMTitleChanged", { title: content.document.title }); + break; + } + }, +}; + +DOMTitleChangedListener.init(); diff --git a/mobile/android/chrome/content/geckoview.js b/mobile/android/chrome/content/geckoview.js index 998427983a07..ffa2bb232b99 100644 --- a/mobile/android/chrome/content/geckoview.js +++ b/mobile/android/chrome/content/geckoview.js @@ -3,24 +3,32 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ "use strict"; -var Cc = Components.classes; -var Ci = Components.interfaces; -var Cu = Components.utils; -var Cr = Components.results; +const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; Cu.import("resource://gre/modules/AppConstants.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Log", - "resource://gre/modules/AndroidLog.jsm", "AndroidLog"); - XPCOMUtils.defineLazyModuleGetter(this, "Services", "resource://gre/modules/Services.jsm", "Services"); -function dump(msg) { - Log.d("View", msg); -} +XPCOMUtils.defineLazyModuleGetter(this, "EventDispatcher", + "resource://gre/modules/Messaging.jsm"); +XPCOMUtils.defineLazyGetter(this, "GlobalEventDispatcher", + () => EventDispatcher.instance); +XPCOMUtils.defineLazyGetter(this, "WindowEventDispatcher", + () => EventDispatcher.for(window)); + +var dump = Cu.import("resource://gre/modules/AndroidLog.jsm", {}) + .AndroidLog.d.bind(null, "View"); + +// GeckoView module imports. +XPCOMUtils.defineLazyModuleGetter(this, "GeckoViewContent", + "resource://gre/modules/GeckoViewContent.jsm"); + +var content; function startup() { - dump("zerdatime " + Date.now() + " - geckoview chrome startup finished."); + dump("zerdatime " + Date.now() + " - geckoview chrome startup finished."); + + content = new GeckoViewContent(window, document.getElementById("content"), WindowEventDispatcher); } diff --git a/mobile/android/chrome/jar.mn b/mobile/android/chrome/jar.mn index 538a025bd0d4..276f8e2694cb 100644 --- a/mobile/android/chrome/jar.mn +++ b/mobile/android/chrome/jar.mn @@ -29,6 +29,7 @@ chrome.jar: content/browser.js (content/browser.js) content/geckoview.xul (content/geckoview.xul) content/geckoview.js (content/geckoview.js) + content/GeckoViewContent.js (content/GeckoViewContent.js) content/PresentationView.xul (content/PresentationView.xul) content/PresentationView.js (content/PresentationView.js) content/bindings/checkbox.xml (content/bindings/checkbox.xml) diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoView.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoView.java index 462abe7def81..984c6ecca565 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoView.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoView.java @@ -14,7 +14,9 @@ import org.mozilla.gecko.annotation.ReflectionTarget; import org.mozilla.gecko.annotation.WrapForJNI; import org.mozilla.gecko.gfx.LayerView; import org.mozilla.gecko.mozglue.JNIObject; +import org.mozilla.gecko.util.BundleEventListener; import org.mozilla.gecko.util.EventCallback; +import org.mozilla.gecko.util.GeckoBundle; import android.app.Activity; import android.content.Context; @@ -39,10 +41,12 @@ public class GeckoView extends LayerView private static final String DEFAULT_SHARED_PREFERENCES_FILE = "GeckoView"; private static final String LOGTAG = "GeckoView"; + private static final boolean DEBUG = false; + private final EventDispatcher eventDispatcher = new EventDispatcher(); private ChromeDelegate mChromeDelegate; - private ContentDelegate mContentDelegate; + /* package */ ContentListener mContentListener; private InputConnectionListener mInputConnectionListener; @@ -108,8 +112,31 @@ public class GeckoView extends LayerView }; } + private class Listener implements BundleEventListener { + /* package */ void registerListeners() { + getEventDispatcher().registerUiThreadListener(this, + "GeckoView:DOMTitleChanged", + null); + } + + @Override + public void handleMessage(final String event, final GeckoBundle message, + final EventCallback callback) { + if (DEBUG) { + Log.d(LOGTAG, "handleMessage: event = " + event); + } + + if ("GeckoView:DOMTitleChanged".equals(event)) { + if (mContentListener != null) { + mContentListener.onTitleChanged(GeckoView.this, message.getString("title")); + } + } + } + } + protected Window window; private boolean stateSaved; + private final Listener listener = new Listener(); public GeckoView(Context context) { super(context); @@ -137,6 +164,7 @@ public class GeckoView extends LayerView GeckoAppShell.setLayerView(this); initializeView(); + listener.registerListeners(); } @Override @@ -342,10 +370,18 @@ public class GeckoView extends LayerView /** * Set the content callback handler. * This will replace the current handler. - * @param content An implementation of ContentDelegate. + * @param content An implementation of ContentListener. */ - public void setContentDelegate(ContentDelegate content) { - mContentDelegate = content; + public void setContentListener(ContentListener content) { + mContentListener = content; + } + + /** + * Get the content callback handler. + * @return The current content callback handler. + */ + public ContentListener getContentListener() { + return mContentListener; } public static void setGeckoInterface(final BaseGeckoInterface geckoInterface) { @@ -435,43 +471,13 @@ public class GeckoView extends LayerView public void onDebugRequest(GeckoView view, GeckoView.PromptResult result); } - public interface ContentDelegate { - /** - * A View has started loading content from the network. - * @param view The GeckoView that initiated the callback. - * @param url The resource being loaded. - */ - public void onPageStart(GeckoView view, String url); - - /** - * A View has finished loading content from the network. - * @param view The GeckoView that initiated the callback. - * @param success Whether the page loaded successfully or an error occurred. - */ - public void onPageStop(GeckoView view, boolean success); - - /** - * A View is displaying content. This page could have been loaded via - * network or from the session history. - * @param view The GeckoView that initiated the callback. - */ - public void onPageShow(GeckoView view); - + public interface ContentListener { /** * A page title was discovered in the content or updated after the content * loaded. * @param view The GeckoView that initiated the callback. * @param title The title sent from the content. */ - public void onReceivedTitle(GeckoView view, String title); - - /** - * A link element was discovered in the content or updated after the content - * loaded that specifies a favicon. - * @param view The GeckoView that initiated the callback. - * @param url The href of the link element specifying the favicon. - * @param size The maximum size specified for the favicon, or -1 for any size. - */ - public void onReceivedFavicon(GeckoView view, String url, int size); + public void onTitleChanged(GeckoView view, String title); } } diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoViewContent.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoViewContent.java deleted file mode 100644 index c08de9fbef09..000000000000 --- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoViewContent.java +++ /dev/null @@ -1,51 +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/. */ - -package org.mozilla.gecko; - -public class GeckoViewContent implements GeckoView.ContentDelegate { - /** - * A View has started loading content from the network. - * @param view The GeckoView that initiated the callback. - * @param url The resource being loaded. - */ - @Override - public void onPageStart(GeckoView view, String url) {} - - /** - * A View has finished loading content from the network. - * @param view The GeckoView that initiated the callback. - * @param success Whether the page loaded successfully or an error occurred. - */ - @Override - public void onPageStop(GeckoView view, boolean success) {} - - /** - * A View is displaying content. This page could have been loaded via - * network or from the session history. - * @param view The GeckoView that initiated the callback. - */ - @Override - public void onPageShow(GeckoView view) {} - - /** - * A page title was discovered in the content or updated after the content - * loaded. - * @param view The GeckoView that initiated the callback. - * @param title The title sent from the content. - */ - @Override - public void onReceivedTitle(GeckoView view, String title) {} - - /** - * A link element was discovered in the content or updated after the content - * loaded that specifies a favicon. - * @param view The GeckoView that initiated the callback. - * @param url The href of the link element specifying the favicon. - * @param size The maximum size specified for the favicon, or -1 for any size. - */ - @Override - public void onReceivedFavicon(GeckoView view, String url, int size) {} -} diff --git a/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/GeckoViewActivity.java b/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/GeckoViewActivity.java index 32aa248e7aa7..db7c420eb4b7 100644 --- a/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/GeckoViewActivity.java +++ b/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/GeckoViewActivity.java @@ -34,7 +34,7 @@ public class GeckoViewActivity extends Activity { mGeckoView = (GeckoView) findViewById(R.id.gecko_view); mGeckoView.setChromeDelegate(new MyGeckoViewChrome()); - mGeckoView.setContentDelegate(new MyGeckoViewContent()); + mGeckoView.setContentListener(new MyGeckoViewContent()); } @Override @@ -89,30 +89,10 @@ public class GeckoViewActivity extends Activity { } } - private class MyGeckoViewContent implements GeckoView.ContentDelegate { + private class MyGeckoViewContent implements GeckoView.ContentListener { @Override - public void onPageStart(GeckoView view, String url) { - - } - - @Override - public void onPageStop(GeckoView view, boolean success) { - - } - - @Override - public void onPageShow(GeckoView view) { - - } - - @Override - public void onReceivedTitle(GeckoView view, String title) { - Log.i(LOGTAG, "Received a title: " + title); - } - - @Override - public void onReceivedFavicon(GeckoView view, String url, int size) { - Log.i(LOGTAG, "Received a favicon URL: " + url); + public void onTitleChanged(GeckoView view, String title) { + Log.i(LOGTAG, "Content title changed to " + title); } } } diff --git a/mobile/android/modules/GeckoViewContent.jsm b/mobile/android/modules/GeckoViewContent.jsm new file mode 100644 index 000000000000..938d85eda70b --- /dev/null +++ b/mobile/android/modules/GeckoViewContent.jsm @@ -0,0 +1,50 @@ +/* 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/. */ + +"use strict"; + +this.EXPORTED_SYMBOLS = ["GeckoViewContent"]; + +const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; + +var dump = Cu.import("resource://gre/modules/AndroidLog.jsm", {}) + .AndroidLog.d.bind(null, "ViewContent"); + +var DEBUG = false; + +class GeckoViewContent { + constructor(_window, _browser, _windowEventDispatcher) { + this.window = _window; + this.browser = _browser; + this.windowEventDispatcher = _windowEventDispatcher; + + this.window.QueryInterface(Ci.nsIDOMChromeWindow).browserDOMWindow = this; + + this.messageManager.loadFrameScript("chrome://browser/content/GeckoViewContent.js", true); + this.messageManager.addMessageListener("GeckoView:DOMTitleChanged", this); + } + + get messageManager() { + return this.browser.messageManager; + } + + handleEvent(event) { + if (DEBUG) { + dump("handleEvent: event.type=" + event.type); + } + } + + // Message manager event handler. + receiveMessage(msg) { + if (DEBUG) { + dump("receiveMessage " + msg.name); + } + + switch (msg.name) { + case "GeckoView:DOMTitleChanged": + this.windowEventDispatcher.sendRequest({ type: "GeckoView:DOMTitleChanged", title: msg.data.title }); + break; + } + } +} diff --git a/mobile/android/modules/moz.build b/mobile/android/modules/moz.build index 77702bb19be0..8dc31b444bfd 100644 --- a/mobile/android/modules/moz.build +++ b/mobile/android/modules/moz.build @@ -30,3 +30,8 @@ EXTRA_JS_MODULES += [ 'SSLExceptions.jsm', 'WebsiteMetadata.jsm' ] + +# GeckoView-sepcific modules added separately. +EXTRA_JS_MODULES += [ + 'GeckoViewContent.jsm' +]