Merge "Remove defunct searchbox implementation from webview." into jb-mr1-dev
This commit is contained in:
@@ -107,9 +107,6 @@ class BrowserFrame extends Handler {
|
||||
// Key store handler when Chromium HTTP stack is used.
|
||||
private KeyStoreHandler mKeyStoreHandler = null;
|
||||
|
||||
// Implementation of the searchbox API.
|
||||
private final SearchBoxImpl mSearchBox;
|
||||
|
||||
// message ids
|
||||
// a message posted when a frame loading is completed
|
||||
static final int FRAME_COMPLETED = 1001;
|
||||
@@ -255,8 +252,6 @@ class BrowserFrame extends Handler {
|
||||
mDatabase = WebViewDatabaseClassic.getInstance(appContext);
|
||||
mWebViewCore = w;
|
||||
|
||||
mSearchBox = new SearchBoxImpl(mWebViewCore, mCallbackProxy);
|
||||
|
||||
AssetManager am = context.getAssets();
|
||||
nativeCreateFrame(w, am, proxy.getBackForwardList());
|
||||
|
||||
@@ -1217,10 +1212,6 @@ class BrowserFrame extends Handler {
|
||||
}
|
||||
}
|
||||
|
||||
/*package*/ SearchBox getSearchBox() {
|
||||
return mSearchBox;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by JNI when processing the X-Auto-Login header.
|
||||
*/
|
||||
|
||||
@@ -117,11 +117,8 @@ class CallbackProxy extends Handler {
|
||||
private static final int ADD_HISTORY_ITEM = 135;
|
||||
private static final int HISTORY_INDEX_CHANGED = 136;
|
||||
private static final int AUTH_CREDENTIALS = 137;
|
||||
private static final int NOTIFY_SEARCHBOX_LISTENERS = 139;
|
||||
private static final int AUTO_LOGIN = 140;
|
||||
private static final int CLIENT_CERT_REQUEST = 141;
|
||||
private static final int SEARCHBOX_IS_SUPPORTED_CALLBACK = 142;
|
||||
private static final int SEARCHBOX_DISPATCH_COMPLETE_CALLBACK = 143;
|
||||
private static final int PROCEEDED_AFTER_SSL_ERROR = 144;
|
||||
|
||||
// Message triggered by the client to resume execution
|
||||
@@ -871,14 +868,6 @@ class CallbackProxy extends Handler {
|
||||
host, realm, username, password);
|
||||
break;
|
||||
}
|
||||
case NOTIFY_SEARCHBOX_LISTENERS: {
|
||||
SearchBoxImpl searchBox = (SearchBoxImpl) mWebView.getSearchBox();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<String> suggestions = (List<String>) msg.obj;
|
||||
searchBox.handleSuggestions(msg.getData().getString("query"), suggestions);
|
||||
break;
|
||||
}
|
||||
case AUTO_LOGIN: {
|
||||
if (mWebViewClient != null) {
|
||||
String realm = msg.getData().getString("realm");
|
||||
@@ -889,19 +878,6 @@ class CallbackProxy extends Handler {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SEARCHBOX_IS_SUPPORTED_CALLBACK: {
|
||||
SearchBoxImpl searchBox = (SearchBoxImpl) mWebView.getSearchBox();
|
||||
Boolean supported = (Boolean) msg.obj;
|
||||
searchBox.handleIsSupportedCallback(supported);
|
||||
break;
|
||||
}
|
||||
case SEARCHBOX_DISPATCH_COMPLETE_CALLBACK: {
|
||||
SearchBoxImpl searchBox = (SearchBoxImpl) mWebView.getSearchBox();
|
||||
Boolean success = (Boolean) msg.obj;
|
||||
searchBox.handleDispatchCompleteCallback(msg.getData().getString("function"),
|
||||
msg.getData().getInt("id"), success);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1629,29 +1605,6 @@ class CallbackProxy extends Handler {
|
||||
return mContext instanceof Activity;
|
||||
}
|
||||
|
||||
void onSearchboxSuggestionsReceived(String query, List<String> suggestions) {
|
||||
Message msg = obtainMessage(NOTIFY_SEARCHBOX_LISTENERS);
|
||||
msg.obj = suggestions;
|
||||
msg.getData().putString("query", query);
|
||||
|
||||
sendMessage(msg);
|
||||
}
|
||||
|
||||
void onIsSupportedCallback(boolean isSupported) {
|
||||
Message msg = obtainMessage(SEARCHBOX_IS_SUPPORTED_CALLBACK);
|
||||
msg.obj = Boolean.valueOf(isSupported);
|
||||
sendMessage(msg);
|
||||
}
|
||||
|
||||
void onSearchboxDispatchCompleteCallback(String function, int id, boolean success) {
|
||||
Message msg = obtainMessage(SEARCHBOX_DISPATCH_COMPLETE_CALLBACK);
|
||||
msg.obj = Boolean.valueOf(success);
|
||||
msg.getData().putString("function", function);
|
||||
msg.getData().putInt("id", id);
|
||||
|
||||
sendMessage(msg);
|
||||
}
|
||||
|
||||
private synchronized void sendMessageToUiThreadSync(Message msg) {
|
||||
sendMessage(msg);
|
||||
WebCoreThreadWatchdog.pause();
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package android.webkit;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Defines the interaction between the browser/renderer and the page running on
|
||||
* a given WebView frame, if the page supports the chromium SearchBox API.
|
||||
*
|
||||
* http://dev.chromium.org/searchbox
|
||||
*
|
||||
* The browser or container app can query the page for search results using
|
||||
* SearchBox.query() and receive suggestions by registering a listener on the
|
||||
* SearchBox object.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public interface SearchBox {
|
||||
/**
|
||||
* Sets the current searchbox query. Note that the caller must call
|
||||
* onchange() to ensure that the search page processes this query.
|
||||
*/
|
||||
void setQuery(String query);
|
||||
|
||||
/**
|
||||
* Verbatim is true if the caller suggests that the search page
|
||||
* treat the current query as a verbatim search query (as opposed to a
|
||||
* partially typed search query). As with setQuery, onchange() must be
|
||||
* called to ensure that the search page processes the query.
|
||||
*/
|
||||
void setVerbatim(boolean verbatim);
|
||||
|
||||
/**
|
||||
* These attributes must contain the offset to the characters that immediately
|
||||
* follow the start and end of the selection in the search box. If there is
|
||||
* no such selection, then both selectionStart and selectionEnd must be the offset
|
||||
* to the character that immediately follows the text entry cursor. In the case
|
||||
* that there is no explicit text entry cursor, the cursor is
|
||||
* implicitly at the end of the input.
|
||||
*/
|
||||
void setSelection(int selectionStart, int selectionEnd);
|
||||
|
||||
/**
|
||||
* Sets the dimensions of the view (if any) that overlaps the current
|
||||
* window object. This is to ensure that the page renders results in
|
||||
* a manner that allows them to not be obscured by such a view. Note
|
||||
* that a call to onresize() is required if these dimensions change.
|
||||
*/
|
||||
void setDimensions(int x, int y, int width, int height);
|
||||
|
||||
/**
|
||||
* Notify the search page of any changes to the searchbox. Such as
|
||||
* a change in the typed query (onchange), the user commiting a given query
|
||||
* (onsubmit), or a change in size of a suggestions dropdown (onresize).
|
||||
*
|
||||
* @param listener an optional listener to notify of the success of the operation,
|
||||
* indicating if the javascript function existed and could be called or not.
|
||||
* It will be called on the UI thread.
|
||||
*/
|
||||
void onchange(SearchBoxListener listener);
|
||||
void onsubmit(SearchBoxListener listener);
|
||||
void onresize(SearchBoxListener listener);
|
||||
void oncancel(SearchBoxListener listener);
|
||||
|
||||
/**
|
||||
* Add and remove listeners to the given Searchbox. Listeners are notified
|
||||
* of any suggestions to the query that the underlying search engine might
|
||||
* provide.
|
||||
*/
|
||||
void addSearchBoxListener(SearchBoxListener l);
|
||||
void removeSearchBoxListener(SearchBoxListener l);
|
||||
|
||||
/**
|
||||
* Indicates if the searchbox API is supported in the current page.
|
||||
*/
|
||||
void isSupported(IsSupportedCallback callback);
|
||||
|
||||
/**
|
||||
* Listeners (if any) will be called on the thread that created the
|
||||
* webview.
|
||||
*/
|
||||
public abstract class SearchBoxListener {
|
||||
public void onSuggestionsReceived(String query, List<String> suggestions) {}
|
||||
public void onChangeComplete(boolean called) {}
|
||||
public void onSubmitComplete(boolean called) {}
|
||||
public void onResizeComplete(boolean called) {}
|
||||
public void onCancelComplete(boolean called) {}
|
||||
}
|
||||
|
||||
interface IsSupportedCallback {
|
||||
void searchBoxIsSupported(boolean supported);
|
||||
}
|
||||
}
|
||||
@@ -1,304 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.webkit;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.webkit.WebViewCore.EventHub;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.json.JSONStringer;
|
||||
|
||||
/**
|
||||
* The default implementation of the SearchBox interface. Implemented
|
||||
* as a java bridge object and a javascript adapter that is called into
|
||||
* by the page hosted in the frame.
|
||||
*/
|
||||
final class SearchBoxImpl implements SearchBox {
|
||||
private static final String TAG = "WebKit.SearchBoxImpl";
|
||||
|
||||
/* package */ static final String JS_INTERFACE_NAME = "searchBoxJavaBridge_";
|
||||
|
||||
/* package */ static final String JS_BRIDGE
|
||||
= "(function()"
|
||||
+ "{"
|
||||
+ "if (!window.chrome) {"
|
||||
+ " window.chrome = {};"
|
||||
+ "}"
|
||||
+ "if (!window.chrome.searchBox) {"
|
||||
+ " var sb = window.chrome.searchBox = {};"
|
||||
+ " sb.setSuggestions = function(suggestions) {"
|
||||
+ " if (window.searchBoxJavaBridge_) {"
|
||||
+ " window.searchBoxJavaBridge_.setSuggestions(JSON.stringify(suggestions));"
|
||||
+ " }"
|
||||
+ " };"
|
||||
+ " sb.setValue = function(valueArray) { sb.value = valueArray[0]; };"
|
||||
+ " sb.value = '';"
|
||||
+ " sb.x = 0;"
|
||||
+ " sb.y = 0;"
|
||||
+ " sb.width = 0;"
|
||||
+ " sb.height = 0;"
|
||||
+ " sb.selectionStart = 0;"
|
||||
+ " sb.selectionEnd = 0;"
|
||||
+ " sb.verbatim = false;"
|
||||
+ "}"
|
||||
+ "})();";
|
||||
|
||||
private static final String SET_QUERY_SCRIPT
|
||||
= "if (window.chrome && window.chrome.searchBox) {"
|
||||
+ " window.chrome.searchBox.setValue(%s);"
|
||||
+ "}";
|
||||
|
||||
private static final String SET_VERBATIM_SCRIPT
|
||||
= "if (window.chrome && window.chrome.searchBox) {"
|
||||
+ " window.chrome.searchBox.verbatim = %1$s;"
|
||||
+ "}";
|
||||
|
||||
private static final String SET_SELECTION_SCRIPT
|
||||
= "if (window.chrome && window.chrome.searchBox) {"
|
||||
+ " var f = window.chrome.searchBox;"
|
||||
+ " f.selectionStart = %d"
|
||||
+ " f.selectionEnd = %d"
|
||||
+ "}";
|
||||
|
||||
private static final String SET_DIMENSIONS_SCRIPT
|
||||
= "if (window.chrome && window.chrome.searchBox) { "
|
||||
+ " var f = window.chrome.searchBox;"
|
||||
+ " f.x = %d;"
|
||||
+ " f.y = %d;"
|
||||
+ " f.width = %d;"
|
||||
+ " f.height = %d;"
|
||||
+ "}";
|
||||
|
||||
private static final String DISPATCH_EVENT_SCRIPT
|
||||
= "if (window.chrome && window.chrome.searchBox && window.chrome.searchBox.on%1$s) {"
|
||||
+ " window.chrome.searchBox.on%1$s();"
|
||||
+ " window.searchBoxJavaBridge_.dispatchCompleteCallback('%1$s', %2$d, true);"
|
||||
+ "} else {"
|
||||
+ " window.searchBoxJavaBridge_.dispatchCompleteCallback('%1$s', %2$d, false);"
|
||||
+ "}";
|
||||
|
||||
private static final String EVENT_CHANGE = "change";
|
||||
private static final String EVENT_SUBMIT = "submit";
|
||||
private static final String EVENT_RESIZE = "resize";
|
||||
private static final String EVENT_CANCEL = "cancel";
|
||||
|
||||
private static final String IS_SUPPORTED_SCRIPT
|
||||
= "if (window.searchBoxJavaBridge_) {"
|
||||
+ " if (window.chrome && window.chrome.sv) {"
|
||||
+ " window.searchBoxJavaBridge_.isSupportedCallback(true);"
|
||||
+ " } else {"
|
||||
+ " window.searchBoxJavaBridge_.isSupportedCallback(false);"
|
||||
+ " }}";
|
||||
|
||||
private final List<SearchBoxListener> mListeners;
|
||||
private final WebViewCore mWebViewCore;
|
||||
private final CallbackProxy mCallbackProxy;
|
||||
private IsSupportedCallback mSupportedCallback;
|
||||
private int mNextEventId = 1;
|
||||
private final HashMap<Integer, SearchBoxListener> mEventCallbacks;
|
||||
|
||||
SearchBoxImpl(WebViewCore webViewCore, CallbackProxy callbackProxy) {
|
||||
mListeners = new ArrayList<SearchBoxListener>();
|
||||
mWebViewCore = webViewCore;
|
||||
mCallbackProxy = callbackProxy;
|
||||
mEventCallbacks = new HashMap<Integer, SearchBoxListener>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setQuery(String query) {
|
||||
final String formattedQuery = jsonSerialize(query);
|
||||
if (formattedQuery != null) {
|
||||
final String js = String.format(SET_QUERY_SCRIPT, formattedQuery);
|
||||
dispatchJs(js);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVerbatim(boolean verbatim) {
|
||||
final String js = String.format(SET_VERBATIM_SCRIPT, String.valueOf(verbatim));
|
||||
dispatchJs(js);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setSelection(int selectionStart, int selectionEnd) {
|
||||
final String js = String.format(SET_SELECTION_SCRIPT, selectionStart, selectionEnd);
|
||||
dispatchJs(js);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDimensions(int x, int y, int width, int height) {
|
||||
final String js = String.format(SET_DIMENSIONS_SCRIPT, x, y, width, height);
|
||||
dispatchJs(js);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onchange(SearchBoxListener callback) {
|
||||
dispatchEvent(EVENT_CHANGE, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onsubmit(SearchBoxListener callback) {
|
||||
dispatchEvent(EVENT_SUBMIT, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onresize(SearchBoxListener callback) {
|
||||
dispatchEvent(EVENT_RESIZE, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void oncancel(SearchBoxListener callback) {
|
||||
dispatchEvent(EVENT_CANCEL, callback);
|
||||
}
|
||||
|
||||
private void dispatchEvent(String eventName, SearchBoxListener callback) {
|
||||
int eventId;
|
||||
if (callback != null) {
|
||||
synchronized(this) {
|
||||
eventId = mNextEventId++;
|
||||
mEventCallbacks.put(eventId, callback);
|
||||
}
|
||||
} else {
|
||||
eventId = 0;
|
||||
}
|
||||
final String js = String.format(DISPATCH_EVENT_SCRIPT, eventName, eventId);
|
||||
dispatchJs(js);
|
||||
}
|
||||
|
||||
private void dispatchJs(String js) {
|
||||
mWebViewCore.sendMessage(EventHub.EXECUTE_JS, js);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSearchBoxListener(SearchBoxListener l) {
|
||||
synchronized (mListeners) {
|
||||
mListeners.add(l);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSearchBoxListener(SearchBoxListener l) {
|
||||
synchronized (mListeners) {
|
||||
mListeners.remove(l);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void isSupported(IsSupportedCallback callback) {
|
||||
mSupportedCallback = callback;
|
||||
dispatchJs(IS_SUPPORTED_SCRIPT);
|
||||
}
|
||||
|
||||
// Called by Javascript through the Java bridge.
|
||||
public void isSupportedCallback(boolean isSupported) {
|
||||
mCallbackProxy.onIsSupportedCallback(isSupported);
|
||||
}
|
||||
|
||||
public void handleIsSupportedCallback(boolean isSupported) {
|
||||
IsSupportedCallback callback = mSupportedCallback;
|
||||
mSupportedCallback = null;
|
||||
if (callback != null) {
|
||||
callback.searchBoxIsSupported(isSupported);
|
||||
}
|
||||
}
|
||||
|
||||
// Called by Javascript through the Java bridge.
|
||||
public void dispatchCompleteCallback(String function, int id, boolean successful) {
|
||||
mCallbackProxy.onSearchboxDispatchCompleteCallback(function, id, successful);
|
||||
}
|
||||
|
||||
public void handleDispatchCompleteCallback(String function, int id, boolean successful) {
|
||||
if (id != 0) {
|
||||
SearchBoxListener listener;
|
||||
synchronized(this) {
|
||||
listener = mEventCallbacks.get(id);
|
||||
mEventCallbacks.remove(id);
|
||||
}
|
||||
if (listener != null) {
|
||||
if (TextUtils.equals(EVENT_CHANGE, function)) {
|
||||
listener.onChangeComplete(successful);
|
||||
} else if (TextUtils.equals(EVENT_SUBMIT, function)) {
|
||||
listener.onSubmitComplete(successful);
|
||||
} else if (TextUtils.equals(EVENT_RESIZE, function)) {
|
||||
listener.onResizeComplete(successful);
|
||||
} else if (TextUtils.equals(EVENT_CANCEL, function)) {
|
||||
listener.onCancelComplete(successful);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This is used as a hackish alternative to javascript escaping.
|
||||
// There appears to be no such functionality in the core framework.
|
||||
private static String jsonSerialize(String query) {
|
||||
JSONStringer stringer = new JSONStringer();
|
||||
try {
|
||||
stringer.array().value(query).endArray();
|
||||
} catch (JSONException e) {
|
||||
Log.w(TAG, "Error serializing query : " + query);
|
||||
return null;
|
||||
}
|
||||
return stringer.toString();
|
||||
}
|
||||
|
||||
// Called by Javascript through the Java bridge.
|
||||
public void setSuggestions(String jsonArguments) {
|
||||
if (jsonArguments == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String query = null;
|
||||
List<String> suggestions = new ArrayList<String>();
|
||||
try {
|
||||
JSONObject suggestionsJson = new JSONObject(jsonArguments);
|
||||
query = suggestionsJson.getString("query");
|
||||
|
||||
final JSONArray suggestionsArray = suggestionsJson.getJSONArray("suggestions");
|
||||
for (int i = 0; i < suggestionsArray.length(); ++i) {
|
||||
final JSONObject suggestion = suggestionsArray.getJSONObject(i);
|
||||
final String value = suggestion.getString("value");
|
||||
if (value != null) {
|
||||
suggestions.add(value);
|
||||
}
|
||||
// We currently ignore the "type" of the suggestion. This isn't
|
||||
// documented anywhere in the API documents.
|
||||
// final String type = suggestions.getString("type");
|
||||
}
|
||||
} catch (JSONException je) {
|
||||
Log.w(TAG, "Error parsing json [" + jsonArguments + "], exception = " + je);
|
||||
return;
|
||||
}
|
||||
|
||||
mCallbackProxy.onSearchboxSuggestionsReceived(query, suggestions);
|
||||
}
|
||||
|
||||
/* package */ void handleSuggestions(String query, List<String> suggestions) {
|
||||
synchronized (mListeners) {
|
||||
for (int i = mListeners.size() - 1; i >= 0; i--) {
|
||||
mListeners.get(i).onSuggestionsReceived(query, suggestions);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5367,10 +5367,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
|
||||
* This is an implementation detail.
|
||||
*/
|
||||
public SearchBox getSearchBox() {
|
||||
if ((mWebViewCore == null) || (mWebViewCore.getBrowserFrame() == null)) {
|
||||
return null;
|
||||
}
|
||||
return mWebViewCore.getBrowserFrame().getSearchBox();
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user