1 // Copyright (c) 2014 Intel Corporation. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 package org.xwalk.core.internal;
7 import java.lang.ref.ReferenceQueue;
8 import java.lang.ref.WeakReference;
9 import java.util.ArrayList;
10 import java.util.HashMap;
14 * This class represents the preferences and could be set by callers.
15 * It is not thread-safe and must be called on the UI thread.
16 * Afterwards, the preference could be read from all threads and can impact
17 * all XWalkViewInternal instances.
19 public class XWalkPreferencesInternal {
20 private static HashMap<String, Boolean> sPrefMap = new HashMap<String, Boolean>();
21 // Here we use WeakReference to make sure the KeyValueChangeListener instance
22 // can be GC-ed to avoid memory leaking issue.
23 private static ArrayList<WeakReference<KeyValueChangeListener> > sListeners =
24 new ArrayList<WeakReference<KeyValueChangeListener> >();
25 private static ReferenceQueue<KeyValueChangeListener> sRefQueue =
26 new ReferenceQueue<KeyValueChangeListener>();
29 * The key string to enable/disable remote debugging.
32 public static final String REMOTE_DEBUGGING = "remote-debugging";
35 * The key string to enable/disable animatable XWalkViewInternal. Default value is
38 * If this key is set to True, the XWalkViewInternal created by Crosswalk can be
39 * transformed and animated. Internally, Crosswalk is alternatively using
40 * TextureView as the backend of XWalkViewInternal.
42 * <a href="http://developer.android.com/reference/android/view/TextureView.html">
43 * TextureView</a> is a kind of
44 * <a href="http://developer.android.com/reference/android/view/View.html">
45 * android.view.View</a> that is different from
46 * <a href="http://developer.android.com/reference/android/view/SurfaceView.html">
47 * SurfaceView</a>. Unlike SurfaceView, it can be resized, transformed and
48 * animated. Once this key is set to True, all XWalkViewInternal will use TextureView
49 * as the rendering target instead of SurfaceView. The downside of TextureView
50 * is, it would consume more graphics memory than SurfaceView and may have
51 * 1~3 extra frames of latency to display updates.
53 * Note this key MUST be set before creating the first XWalkViewInternal, otherwise
54 * a RuntimeException will be thrown.
58 public static final String ANIMATABLE_XWALK_VIEW = "animatable-xwalk-view";
61 * The key string to enable/disable javascript.
63 static final String ENABLE_JAVASCRIPT = "enable-javascript";
66 * The key string to allow/disallow javascript to open
67 * window automatically.
69 static final String JAVASCRIPT_CAN_OPEN_WINDOW =
70 "javascript-can-open-window";
73 * The key string to allow/disallow having universal access
76 static final String ALLOW_UNIVERSAL_ACCESS_FROM_FILE =
77 "allow-universal-access-from-file";
80 sPrefMap.put(REMOTE_DEBUGGING, Boolean.FALSE);
81 sPrefMap.put(ANIMATABLE_XWALK_VIEW, Boolean.FALSE);
82 sPrefMap.put(ENABLE_JAVASCRIPT, Boolean.TRUE);
83 sPrefMap.put(JAVASCRIPT_CAN_OPEN_WINDOW, Boolean.TRUE);
85 ALLOW_UNIVERSAL_ACCESS_FROM_FILE, Boolean.FALSE);
89 * Set a preference value into Crosswalk. An exception will be thrown if
90 * the key for the preference is not valid.
91 * @param key the string name of the key.
92 * @param enabled true if setting it as enabled.
95 public static synchronized void setValue(String key, boolean enabled) throws RuntimeException {
97 // If the listener list is not empty, we consider the preference is
98 // loaded by Crosswalk and taken effect already.
99 if (key == ANIMATABLE_XWALK_VIEW && !sListeners.isEmpty()) {
100 throw new RuntimeException("Warning: the preference key " + key +
101 " can not be set if the preference is already loaded by Crosswalk");
103 if (sPrefMap.get(key) != enabled) {
104 sPrefMap.put(key, new Boolean(enabled));
105 onKeyValueChanged(key, enabled);
110 * Get a preference value from Crosswalk. An exception will be thrown if
111 * the key for the preference is not valid.
112 * @param key the string name of the key.
113 * @return true if it's enabled.
116 public static synchronized boolean getValue(String key) throws RuntimeException {
118 return sPrefMap.get(key);
121 // TODO(yongsheng): I believe this is needed?
122 /*public static synchronized void setValue(String key, int value) throws RuntimeException {
125 static synchronized void load(KeyValueChangeListener listener) {
126 // Load current settings for initialization of a listener implementor.
127 for (Map.Entry<String, Boolean> entry : sPrefMap.entrySet()) {
128 listener.onKeyValueChanged(entry.getKey(), entry.getValue());
131 registerListener(listener);
134 static synchronized void unload(KeyValueChangeListener listener) {
135 unregisterListener(listener);
138 // Listen to value changes.
139 interface KeyValueChangeListener {
140 public void onKeyValueChanged(String key, boolean value);
143 private static synchronized void registerListener(KeyValueChangeListener listener) {
144 removeEnqueuedReference();
145 WeakReference<KeyValueChangeListener> weakListener =
146 new WeakReference<KeyValueChangeListener>(listener, sRefQueue);
147 sListeners.add(weakListener);
150 private static synchronized void unregisterListener(KeyValueChangeListener listener) {
151 removeEnqueuedReference();
152 for (WeakReference<KeyValueChangeListener> weakListener : sListeners) {
153 if (weakListener.get() == listener) {
154 sListeners.remove(weakListener);
160 private static void onKeyValueChanged(String key, boolean enabled) {
161 for (WeakReference<KeyValueChangeListener> weakListener : sListeners) {
162 KeyValueChangeListener listener = weakListener.get();
163 if (listener != null) listener.onKeyValueChanged(key, enabled);
167 private static void checkKey(String key) throws RuntimeException {
168 removeEnqueuedReference();
169 if (!sPrefMap.containsKey(key)) {
170 throw new RuntimeException("Warning: the preference key " + key +
171 " is not supported by Crosswalk.");
176 * Internal method to keep track of weak references and remove the enqueued
177 * references from listener list by polling the reference queue.
179 @SuppressWarnings("unchecked")
180 private static void removeEnqueuedReference() {
181 WeakReference<KeyValueChangeListener> toRemove;
182 while ((toRemove = (WeakReference<KeyValueChangeListener>) sRefQueue.poll()) != null) {
183 sListeners.remove(toRemove);