Bug 1413698 - 3. Recorganize GeckoViewSettings; r=snorp
* Move the chromeUri and screenId settings to GeckoViewSettings.
* Add a private data-dir setting that the debugger-socket-dir setting
falls backs to. Set the data-dir setting inside `GeckoSession.openWindow`.
* Add optional init-only and values properties for settings.
* Use integer constants for display-mode setting.
MozReview-Commit-ID: HgJg0t0oade
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoSession.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoSession.java
@@ -338,56 +338,50 @@ public class GeckoSession implements Par
if ("GeckoView:Prompt".equals(event)) {
handlePromptEvent(GeckoSession.this, message, callback);
}
}
}
protected Window mWindow;
private GeckoViewSettings mSettings;
- private String mChromeUri;
- private int mScreenId = 0; // default to the primary screen
public GeckoSession() {
this(/* settings */ null);
}
public GeckoSession(final GeckoViewSettings settings) {
if (settings == null) {
- mSettings = new GeckoViewSettings(mEventDispatcher);
+ mSettings = new GeckoViewSettings(this);
} else {
- mSettings = new GeckoViewSettings(settings, mEventDispatcher);
+ mSettings = new GeckoViewSettings(settings, this);
}
mListener.registerListeners();
}
/* package */ void transferFrom(final GeckoSession session) {
if (isOpen()) {
throw new IllegalStateException("Session is open");
}
+
mWindow = session.mWindow;
+ mSettings = new GeckoViewSettings(session.mSettings, this);
session.mWindow = null;
-
- mSettings = new GeckoViewSettings(session.mSettings, getEventDispatcher());
- mChromeUri = session.mChromeUri;
- mScreenId = session.mScreenId;
}
@Override // Parcelable
public int describeContents() {
return 0;
}
@Override // Parcelable
public void writeToParcel(Parcel out, int flags) {
out.writeStrongInterface(mWindow);
out.writeParcelable(mSettings, flags);
- out.writeString(mChromeUri);
- out.writeInt(mScreenId);
}
// AIDL code may call readFromParcel even though it's not part of Parcelable.
public void readFromParcel(final Parcel source) {
if (isOpen()) {
throw new IllegalStateException("Session is open");
}
@@ -397,20 +391,17 @@ public class GeckoSession implements Par
if (window instanceof Window) {
mWindow = (Window) window;
} else {
mWindow = null;
}
final GeckoViewSettings settings =
source.readParcelable(getClass().getClassLoader());
- mSettings = new GeckoViewSettings(settings, getEventDispatcher());
-
- mChromeUri = source.readString();
- mScreenId = source.readInt();
+ mSettings = new GeckoViewSettings(settings, this);
}
public static final Creator<GeckoSession> CREATOR = new Creator<GeckoSession>() {
@Override
public GeckoSession createFromParcel(final Parcel in) {
final GeckoSession session = new GeckoSession();
session.readFromParcel(in);
return session;
@@ -447,86 +438,54 @@ public class GeckoSession implements Par
}
final int flags = multiprocess ? GeckoThread.FLAG_PRELOAD_CHILD : 0;
if (GeckoThread.initMainProcess(/* profile */ null, geckoArgs, flags)) {
GeckoThread.launch();
}
}
- /**
- * Return the URI of the underlying chrome window opened or to be opened, or null if
- * using the default GeckoSession URI.
- *
- * @return Current chrome URI or null.
- */
- public String getChromeUri() {
- return mChromeUri;
- }
-
- /**
- * Set the URI of the underlying chrome window to be opened, or null to use the
- * default GeckoSession URI. Can only be called before the chrome window is opened during
- * {@link #onAttachedToWindow}.
- *
- * @param uri New chrome URI or null.
- */
- public void setChromeUri(final String uri) {
- if (isOpen()) {
- throw new IllegalStateException("Session is open");
- }
- mChromeUri = uri;
- }
-
- public int getScreenId() {
- return mScreenId;
- }
-
- public void setScreenId(final int id) {
- if (isOpen()) {
- throw new IllegalStateException("Session is open");
- }
- mScreenId = id;
- }
-
public boolean isOpen() {
return mWindow != null;
}
public void openWindow(final Context appContext) {
if (isOpen()) {
throw new IllegalStateException("Session is open");
}
if (!GeckoThread.isLaunched()) {
final boolean multiprocess =
mSettings.getBoolean(GeckoViewSettings.USE_MULTIPROCESS);
preload(appContext, /* geckoArgs */ null, multiprocess);
}
- if (mSettings.getString(GeckoViewSettings.DEBUGGER_SOCKET_DIR) == null) {
- mSettings.setString(GeckoViewSettings.DEBUGGER_SOCKET_DIR,
+ if (mSettings.getString(GeckoViewSettings.DATA_DIR) == null) {
+ mSettings.setString(GeckoViewSettings.DATA_DIR,
appContext.getApplicationInfo().dataDir);
}
+ final String chromeUri = mSettings.getString(GeckoViewSettings.CHROME_URI);
+ final int screenId = mSettings.getInt(GeckoViewSettings.SCREEN_ID);
+ final boolean isPrivate = mSettings.getBoolean(GeckoViewSettings.USE_PRIVATE_MODE);
+
mWindow = new Window(mNativeQueue);
if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) {
Window.open(mWindow, mEventDispatcher, mSettings.asBundle(),
- mChromeUri, mScreenId,
- mSettings.getBoolean(GeckoViewSettings.USE_PRIVATE_MODE));
+ chromeUri, screenId, isPrivate);
} else {
GeckoThread.queueNativeCallUntil(
GeckoThread.State.PROFILE_READY,
Window.class, "open",
Window.class, mWindow,
EventDispatcher.class, mEventDispatcher,
GeckoBundle.class, mSettings.asBundle(),
- String.class, mChromeUri,
- mScreenId, mSettings.getBoolean(GeckoViewSettings.USE_PRIVATE_MODE));
+ String.class, chromeUri,
+ screenId, isPrivate);
}
}
public void attachView(final GeckoView view) {
if (view == null) {
return;
}
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoViewSettings.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoViewSettings.java
@@ -7,160 +7,184 @@
package org.mozilla.gecko;
import org.mozilla.gecko.util.GeckoBundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
+import java.util.Arrays;
+import java.util.Collection;
+
public final class GeckoViewSettings implements Parcelable {
private static final String LOGTAG = "GeckoViewSettings";
private static final boolean DEBUG = false;
- private static class Key<T> {
- private final String text;
+ // This needs to match nsIDocShell.idl
+ public static final int DISPLAY_MODE_BROWSER = 0;
+ public static final int DISPLAY_MODE_MINIMAL_UI = 1;
+ public static final int DISPLAY_MODE_STANDALONE = 2;
+ public static final int DISPLAY_MODE_FULLSCREEN = 3;
- public Key(final String text) {
- this.text = text;
+ private static class Key<T> {
+ public final String name;
+ public final boolean initOnly;
+ public final Collection<T> values;
+
+ public Key(final String name) {
+ this(name, /* initOnly */ false, /* values */ null);
+ }
+
+ public Key(final String name, final boolean initOnly, final Collection<T> values) {
+ this.name = name;
+ this.initOnly = initOnly;
+ this.values = values;
}
}
- public enum DisplayMode {
- // This needs to match nsIDocShell.idl
- BROWSER(0),
- MINIMAL_UI(1),
- STANDALONE(2),
- FULLSCREEN(3);
-
- private final int mMode;
-
- DisplayMode(int mode) {
- mMode = mode;
- }
-
- public int value() {
- return mMode;
- }
- }
+ /**
+ * Key to set the chrome window URI, or null to use default URI.
+ * Read-only once session is open.
+ */
+ public static final Key<String> CHROME_URI =
+ new Key<String>("chromeUri", /* initOnly */ true, /* values */ null);
+ /**
+ * Key to set the window screen ID, or 0 to use default ID.
+ * Read-only once session is open.
+ */
+ public static final Key<Integer> SCREEN_ID =
+ new Key<Integer>("screenId", /* initOnly */ true, /* values */ null);
/*
- * Key to enabled and disable tracking protection.
+ * Key to enable and disable tracking protection.
*/
public static final Key<Boolean> USE_TRACKING_PROTECTION =
new Key<Boolean>("useTrackingProtection");
/*
- * Key to enabled and disable private mode browsing.
+ * Key to enable and disable private mode browsing.
+ * Read-only once session is open.
*/
public static final Key<Boolean> USE_PRIVATE_MODE =
- new Key<Boolean>("usePrivateMode");
+ new Key<Boolean>("usePrivateMode", /* initOnly */ true, /* values */ null);
/*
- * Key to enabled and disable multiprocess browsing (e10s).
- * Note: can only be set during GeckoView initialization, changes during an
- * active GeckoView session will be ignored.
+ * Key to enable and disable multiprocess browsing (e10s).
+ * Read-only once session is open.
*/
public static final Key<Boolean> USE_MULTIPROCESS =
- new Key<Boolean>("useMultiprocess");
+ new Key<Boolean>("useMultiprocess", /* initOnly */ true, /* values */ null);
/*
* Key to specify which display-mode we should use
*/
public static final Key<Integer> DISPLAY_MODE =
- new Key<Integer>("displayMode");
+ new Key<Integer>("displayMode", /* initOnly */ false,
+ Arrays.asList(DISPLAY_MODE_BROWSER, DISPLAY_MODE_MINIMAL_UI,
+ DISPLAY_MODE_STANDALONE, DISPLAY_MODE_FULLSCREEN));
public static final Key<Boolean> USE_REMOTE_DEBUGGER =
new Key<Boolean>("useRemoteDebugger");
public static final Key<String> DEBUGGER_SOCKET_DIR =
new Key<String>("debuggerSocketDir");
- private final EventDispatcher mEventDispatcher;
+ /* package */ static final Key<String> DATA_DIR =
+ new Key<String>("dataDir", /* initOnly */ true, /* values */ null);
+
+ private final GeckoSession mSession;
private final GeckoBundle mBundle;
public GeckoViewSettings() {
this(null);
}
- /* package */ GeckoViewSettings(EventDispatcher eventDispatcher) {
- mEventDispatcher = eventDispatcher;
+ /* package */ GeckoViewSettings(final GeckoSession session) {
+ mSession = session;
mBundle = new GeckoBundle();
- setBoolean(USE_TRACKING_PROTECTION, false);
- setBoolean(USE_PRIVATE_MODE, false);
- setBoolean(USE_MULTIPROCESS, true);
- setInt(DISPLAY_MODE, DisplayMode.BROWSER.value());
- setBoolean(USE_REMOTE_DEBUGGER, false);
- // Set in GeckoView.init().
- setString(DEBUGGER_SOCKET_DIR, ".");
+ mBundle.putString(CHROME_URI.name, null);
+ mBundle.putInt(SCREEN_ID.name, 0);
+ mBundle.putBoolean(USE_TRACKING_PROTECTION.name, false);
+ mBundle.putBoolean(USE_PRIVATE_MODE.name, false);
+ mBundle.putBoolean(USE_MULTIPROCESS.name, true);
+ mBundle.putInt(DISPLAY_MODE.name, DISPLAY_MODE_BROWSER);
+ mBundle.putBoolean(USE_REMOTE_DEBUGGER.name, false);
+ mBundle.putString(DEBUGGER_SOCKET_DIR.name, null);
}
- /* package */ GeckoViewSettings(GeckoViewSettings settings, EventDispatcher eventDispatcher) {
+ /* package */ GeckoViewSettings(final GeckoViewSettings settings,
+ final GeckoSession session) {
+ mSession = session;
mBundle = new GeckoBundle(settings.mBundle);
- mEventDispatcher = eventDispatcher;
}
- public void setBoolean(final Key<Boolean> key, boolean value) {
+ public void setBoolean(final Key<Boolean> key, final boolean value) {
synchronized (mBundle) {
- final Object old = mBundle.get(key.text);
- if (old != null && old.equals(value)) {
- return;
+ if (valueChangedLocked(key, value)) {
+ mBundle.putBoolean(key.name, value);
+ dispatchUpdate();
}
- mBundle.putBoolean(key.text, value);
}
- dispatchUpdate();
}
public boolean getBoolean(final Key<Boolean> key) {
synchronized (mBundle) {
- return mBundle.getBoolean(key.text);
+ return mBundle.getBoolean(key.name);
}
}
- public void setInt(final Key<Integer> key, int value) {
+ public void setInt(final Key<Integer> key, final int value) {
synchronized (mBundle) {
- final Object old = mBundle.get(key.text);
- if (old != null && old.equals(value)) {
- return;
+ if (valueChangedLocked(key, value)) {
+ mBundle.putInt(key.name, value);
+ dispatchUpdate();
}
- mBundle.putInt(key.text, value);
}
- dispatchUpdate();
}
public int getInt(final Key<Integer> key) {
synchronized (mBundle) {
- return mBundle.getInt(key.text);
+ return mBundle.getInt(key.name);
}
}
public void setString(final Key<String> key, final String value) {
synchronized (mBundle) {
- final Object old = mBundle.get(key.text);
- if (old != null && old.equals(value)) {
- return;
+ if (valueChangedLocked(key, value)) {
+ mBundle.putString(key.name, value);
+ dispatchUpdate();
}
- mBundle.putString(key.text, value);
}
- dispatchUpdate();
}
public String getString(final Key<String> key) {
synchronized (mBundle) {
- return mBundle.getString(key.text);
+ return mBundle.getString(key.name);
}
}
/* package */ GeckoBundle asBundle() {
return mBundle;
}
+ private <T> boolean valueChangedLocked(final Key<T> key, T value) {
+ if (key.initOnly && mSession != null && mSession.isOpen()) {
+ throw new IllegalStateException("Read-only property");
+ } else if (key.values != null && !key.values.contains(value)) {
+ throw new IllegalArgumentException("Invalid value");
+ }
+
+ final Object old = mBundle.get(key.name);
+ return (old != value) && (old == null || !old.equals(value));
+ }
+
private void dispatchUpdate() {
- if (mEventDispatcher != null) {
- mEventDispatcher.dispatch("GeckoView:UpdateSettings", null);
+ if (mSession != null) {
+ mSession.getEventDispatcher().dispatch("GeckoView:UpdateSettings", null);
}
}
@Override // Parcelable
public int describeContents() {
return 0;
}
--- a/mobile/android/modules/geckoview/GeckoViewRemoteDebugger.jsm
+++ b/mobile/android/modules/geckoview/GeckoViewRemoteDebugger.jsm
@@ -51,17 +51,17 @@ class GeckoViewRemoteDebugger extends Ge
DebuggerServer.allowChromeProcess = true;
}
this._isEnabled = true;
this._usbDebugger.stop();
let windowId = this.window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils)
.outerWindowID;
- let portOrPath = this.settings.debuggerSocketDir +
+ let portOrPath = (this.settings.debuggerSocketDir || this.settings.dataDir) +
"/firefox-debugger-socket-" +
windowId;
this._usbDebugger.start(portOrPath);
}
unregister() {
this._isEnabled = false;
this._usbDebugger.stop();