Loading core/java/android/webkit/BrowserFrame.java +24 −16 Original line number Diff line number Diff line Loading @@ -46,7 +46,6 @@ import java.lang.ref.WeakReference; import java.net.URLEncoder; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Iterator; Loading Loading @@ -89,6 +88,9 @@ 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; Loading Loading @@ -225,6 +227,9 @@ class BrowserFrame extends Handler { sConfigCallback.addHandler(this); mJSInterfaceMap = javascriptInterfaces; if (mJSInterfaceMap == null) { mJSInterfaceMap = new HashMap<String, Object>(); } mSettings = settings; mContext = context; Loading @@ -232,6 +237,9 @@ class BrowserFrame extends Handler { mDatabase = WebViewDatabase.getInstance(appContext); mWebViewCore = w; mSearchBox = new SearchBoxImpl(mWebViewCore, mCallbackProxy); mJSInterfaceMap.put(SearchBoxImpl.JS_INTERFACE_NAME, mSearchBox); AssetManager am = context.getAssets(); nativeCreateFrame(w, am, proxy.getBackForwardList()); Loading Loading @@ -587,17 +595,17 @@ class BrowserFrame extends Handler { * We should re-attach any attached js interfaces. */ private void windowObjectCleared(int nativeFramePointer) { if (mJSInterfaceMap != null) { Iterator iter = mJSInterfaceMap.keySet().iterator(); Iterator<String> iter = mJSInterfaceMap.keySet().iterator(); while (iter.hasNext()) { String interfaceName = (String) iter.next(); String interfaceName = iter.next(); Object object = mJSInterfaceMap.get(interfaceName); if (object != null) { nativeAddJavascriptInterface(nativeFramePointer, mJSInterfaceMap.get(interfaceName), interfaceName); } } } stringByEvaluatingJavaScriptFromString(SearchBoxImpl.JS_BRIDGE); } /** Loading @@ -620,16 +628,11 @@ class BrowserFrame extends Handler { public void addJavascriptInterface(Object obj, String interfaceName) { assert obj != null; removeJavascriptInterface(interfaceName); if (mJSInterfaceMap == null) { mJSInterfaceMap = new HashMap<String, Object>(); } mJSInterfaceMap.put(interfaceName, obj); } public void removeJavascriptInterface(String interfaceName) { if (mJSInterfaceMap == null) { return; } if (mJSInterfaceMap.containsKey(interfaceName)) { mJSInterfaceMap.remove(interfaceName); } Loading Loading @@ -1234,6 +1237,11 @@ class BrowserFrame extends Handler { } } /*package*/ SearchBox getSearchBox() { return mSearchBox; } //========================================================================== // native functions //========================================================================== Loading core/java/android/webkit/CallbackProxy.java +16 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import com.android.internal.R; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap; import java.util.List; import java.util.Map; /** Loading Loading @@ -115,6 +116,7 @@ class CallbackProxy extends Handler { private static final int HISTORY_INDEX_CHANGED = 136; private static final int AUTH_CREDENTIALS = 137; private static final int SET_INSTALLABLE_WEBAPP = 138; private static final int NOTIFY_SEARCHBOX_LISTENERS = 139; // Message triggered by the client to resume execution private static final int NOTIFY = 200; Loading Loading @@ -781,6 +783,12 @@ class CallbackProxy extends Handler { mWebChromeClient.setInstallableWebApp(); } 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); } } Loading Loading @@ -1557,4 +1565,12 @@ class CallbackProxy extends Handler { // See bug 3166409 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); } } core/java/android/webkit/SearchBox.java 0 → 100644 +92 −0 Original line number Diff line number Diff line /* * 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 pending API council approval. */ 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). */ void onchange(); void onsubmit(); void onresize(); void oncancel(); /** * 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); /** * Listeners (if any) will be called on the thread that created the * webview. */ interface SearchBoxListener { void onSuggestionsReceived(String query, List<String> suggestions); } } core/java/android/webkit/SearchBoxImpl.java 0 → 100644 +227 −0 Original line number Diff line number Diff line /* * 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.util.Log; import android.webkit.WebViewCore.EventHub; import java.util.ArrayList; 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 = %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(); }"; private final List<SearchBoxListener> mListeners; private final WebViewCore mWebViewCore; private final CallbackProxy mCallbackProxy; SearchBoxImpl(WebViewCore webViewCore, CallbackProxy callbackProxy) { mListeners = new ArrayList<SearchBoxListener>(); mWebViewCore = webViewCore; mCallbackProxy = callbackProxy; } @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() { dispatchEvent("change"); } @Override public void onsubmit() { dispatchEvent("submit"); } @Override public void onresize() { dispatchEvent("resize"); } @Override public void oncancel() { dispatchEvent("cancel"); } private void dispatchEvent(String eventName) { final String js = String.format(DISPATCH_EVENT_SCRIPT, eventName); 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); } } // This is used as a hackish alternative to javascript escaping. // There appears to be no such functionality in the core framework. private 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); } } } } core/java/android/webkit/WebView.java +8 −1 Original line number Diff line number Diff line Loading @@ -5032,6 +5032,13 @@ public class WebView extends AbsoluteLayout return copiedSomething; } /** * @hide pending API Council approval. */ public SearchBox getSearchBox() { return mWebViewCore.getBrowserFrame().getSearchBox(); } /** * Returns the currently highlighted text as a string. */ Loading Loading @@ -8389,7 +8396,7 @@ public class WebView extends AbsoluteLayout private native void nativeSetFindIsUp(boolean isUp); private native void nativeSetHeightCanMeasure(boolean measure); private native void nativeSetBaseLayer(int layer, Rect invalRect, boolean showVisualIndciator); boolean showVisualIndicator); private native void nativeShowCursorTimed(); private native void nativeReplaceBaseContent(int content); private native void nativeCopyBaseContentToPicture(Picture pict); Loading Loading
core/java/android/webkit/BrowserFrame.java +24 −16 Original line number Diff line number Diff line Loading @@ -46,7 +46,6 @@ import java.lang.ref.WeakReference; import java.net.URLEncoder; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Iterator; Loading Loading @@ -89,6 +88,9 @@ 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; Loading Loading @@ -225,6 +227,9 @@ class BrowserFrame extends Handler { sConfigCallback.addHandler(this); mJSInterfaceMap = javascriptInterfaces; if (mJSInterfaceMap == null) { mJSInterfaceMap = new HashMap<String, Object>(); } mSettings = settings; mContext = context; Loading @@ -232,6 +237,9 @@ class BrowserFrame extends Handler { mDatabase = WebViewDatabase.getInstance(appContext); mWebViewCore = w; mSearchBox = new SearchBoxImpl(mWebViewCore, mCallbackProxy); mJSInterfaceMap.put(SearchBoxImpl.JS_INTERFACE_NAME, mSearchBox); AssetManager am = context.getAssets(); nativeCreateFrame(w, am, proxy.getBackForwardList()); Loading Loading @@ -587,17 +595,17 @@ class BrowserFrame extends Handler { * We should re-attach any attached js interfaces. */ private void windowObjectCleared(int nativeFramePointer) { if (mJSInterfaceMap != null) { Iterator iter = mJSInterfaceMap.keySet().iterator(); Iterator<String> iter = mJSInterfaceMap.keySet().iterator(); while (iter.hasNext()) { String interfaceName = (String) iter.next(); String interfaceName = iter.next(); Object object = mJSInterfaceMap.get(interfaceName); if (object != null) { nativeAddJavascriptInterface(nativeFramePointer, mJSInterfaceMap.get(interfaceName), interfaceName); } } } stringByEvaluatingJavaScriptFromString(SearchBoxImpl.JS_BRIDGE); } /** Loading @@ -620,16 +628,11 @@ class BrowserFrame extends Handler { public void addJavascriptInterface(Object obj, String interfaceName) { assert obj != null; removeJavascriptInterface(interfaceName); if (mJSInterfaceMap == null) { mJSInterfaceMap = new HashMap<String, Object>(); } mJSInterfaceMap.put(interfaceName, obj); } public void removeJavascriptInterface(String interfaceName) { if (mJSInterfaceMap == null) { return; } if (mJSInterfaceMap.containsKey(interfaceName)) { mJSInterfaceMap.remove(interfaceName); } Loading Loading @@ -1234,6 +1237,11 @@ class BrowserFrame extends Handler { } } /*package*/ SearchBox getSearchBox() { return mSearchBox; } //========================================================================== // native functions //========================================================================== Loading
core/java/android/webkit/CallbackProxy.java +16 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ import com.android.internal.R; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap; import java.util.List; import java.util.Map; /** Loading Loading @@ -115,6 +116,7 @@ class CallbackProxy extends Handler { private static final int HISTORY_INDEX_CHANGED = 136; private static final int AUTH_CREDENTIALS = 137; private static final int SET_INSTALLABLE_WEBAPP = 138; private static final int NOTIFY_SEARCHBOX_LISTENERS = 139; // Message triggered by the client to resume execution private static final int NOTIFY = 200; Loading Loading @@ -781,6 +783,12 @@ class CallbackProxy extends Handler { mWebChromeClient.setInstallableWebApp(); } 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); } } Loading Loading @@ -1557,4 +1565,12 @@ class CallbackProxy extends Handler { // See bug 3166409 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); } }
core/java/android/webkit/SearchBox.java 0 → 100644 +92 −0 Original line number Diff line number Diff line /* * 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 pending API council approval. */ 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). */ void onchange(); void onsubmit(); void onresize(); void oncancel(); /** * 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); /** * Listeners (if any) will be called on the thread that created the * webview. */ interface SearchBoxListener { void onSuggestionsReceived(String query, List<String> suggestions); } }
core/java/android/webkit/SearchBoxImpl.java 0 → 100644 +227 −0 Original line number Diff line number Diff line /* * 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.util.Log; import android.webkit.WebViewCore.EventHub; import java.util.ArrayList; 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 = %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(); }"; private final List<SearchBoxListener> mListeners; private final WebViewCore mWebViewCore; private final CallbackProxy mCallbackProxy; SearchBoxImpl(WebViewCore webViewCore, CallbackProxy callbackProxy) { mListeners = new ArrayList<SearchBoxListener>(); mWebViewCore = webViewCore; mCallbackProxy = callbackProxy; } @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() { dispatchEvent("change"); } @Override public void onsubmit() { dispatchEvent("submit"); } @Override public void onresize() { dispatchEvent("resize"); } @Override public void oncancel() { dispatchEvent("cancel"); } private void dispatchEvent(String eventName) { final String js = String.format(DISPATCH_EVENT_SCRIPT, eventName); 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); } } // This is used as a hackish alternative to javascript escaping. // There appears to be no such functionality in the core framework. private 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); } } } }
core/java/android/webkit/WebView.java +8 −1 Original line number Diff line number Diff line Loading @@ -5032,6 +5032,13 @@ public class WebView extends AbsoluteLayout return copiedSomething; } /** * @hide pending API Council approval. */ public SearchBox getSearchBox() { return mWebViewCore.getBrowserFrame().getSearchBox(); } /** * Returns the currently highlighted text as a string. */ Loading Loading @@ -8389,7 +8396,7 @@ public class WebView extends AbsoluteLayout private native void nativeSetFindIsUp(boolean isUp); private native void nativeSetHeightCanMeasure(boolean measure); private native void nativeSetBaseLayer(int layer, Rect invalRect, boolean showVisualIndciator); boolean showVisualIndicator); private native void nativeShowCursorTimed(); private native void nativeReplaceBaseContent(int content); private native void nativeCopyBaseContentToPicture(Picture pict); Loading