BrowserFrame.java revision 658ab7d787f64987d7c45aae08e5a12a073afe78
1/* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.webkit; 18 19import android.content.Context; 20import android.content.res.AssetManager; 21import android.graphics.Bitmap; 22import android.net.ParseException; 23import android.net.WebAddress; 24import android.net.http.SslCertificate; 25import android.os.Handler; 26import android.os.Message; 27import android.util.Log; 28import android.util.TypedValue; 29 30import junit.framework.Assert; 31 32import java.net.URLEncoder; 33import java.util.HashMap; 34import java.util.Iterator; 35 36class BrowserFrame extends Handler { 37 38 private static final String LOGTAG = "webkit"; 39 40 /** 41 * Cap the number of LoadListeners that will be instantiated, so 42 * we don't blow the GREF count. Attempting to queue more than 43 * this many requests will prompt an error() callback on the 44 * request's LoadListener 45 */ 46 private final static int MAX_OUTSTANDING_REQUESTS = 300; 47 48 private final CallbackProxy mCallbackProxy; 49 private final WebSettings mSettings; 50 private final Context mContext; 51 private final WebViewDatabase mDatabase; 52 private final WebViewCore mWebViewCore; 53 /* package */ boolean mLoadInitFromJava; 54 private int mLoadType; 55 private boolean mFirstLayoutDone = true; 56 private boolean mCommitted = true; 57 58 // Is this frame the main frame? 59 private boolean mIsMainFrame; 60 61 // Attached Javascript interfaces 62 private HashMap mJSInterfaceMap; 63 64 // message ids 65 // a message posted when a frame loading is completed 66 static final int FRAME_COMPLETED = 1001; 67 // a message posted when the user decides the policy 68 static final int POLICY_FUNCTION = 1003; 69 70 // Note: need to keep these in sync with FrameLoaderTypes.h in native 71 static final int FRAME_LOADTYPE_STANDARD = 0; 72 static final int FRAME_LOADTYPE_BACK = 1; 73 static final int FRAME_LOADTYPE_FORWARD = 2; 74 static final int FRAME_LOADTYPE_INDEXEDBACKFORWARD = 3; 75 static final int FRAME_LOADTYPE_RELOAD = 4; 76 static final int FRAME_LOADTYPE_RELOADALLOWINGSTALEDATA = 5; 77 static final int FRAME_LOADTYPE_SAME = 6; 78 static final int FRAME_LOADTYPE_REDIRECT = 7; 79 static final int FRAME_LOADTYPE_REPLACE = 8; 80 81 // A progress threshold to switch from history Picture to live Picture 82 private static final int TRANSITION_SWITCH_THRESHOLD = 75; 83 84 // This is a field accessed by native code as well as package classes. 85 /*package*/ int mNativeFrame; 86 87 // Static instance of a JWebCoreJavaBridge to handle timer and cookie 88 // requests from WebCore. 89 static JWebCoreJavaBridge sJavaBridge; 90 91 /** 92 * Create a new BrowserFrame to be used in an application. 93 * @param context An application context to use when retrieving assets. 94 * @param w A WebViewCore used as the view for this frame. 95 * @param proxy A CallbackProxy for posting messages to the UI thread and 96 * querying a client for information. 97 * @param settings A WebSettings object that holds all settings. 98 * XXX: Called by WebCore thread. 99 */ 100 public BrowserFrame(Context context, WebViewCore w, CallbackProxy proxy, 101 WebSettings settings) { 102 // Create a global JWebCoreJavaBridge to handle timers and 103 // cookies in the WebCore thread. 104 if (sJavaBridge == null) { 105 sJavaBridge = new JWebCoreJavaBridge(); 106 // set WebCore native cache size 107 sJavaBridge.setCacheSize(4 * 1024 * 1024); 108 // initialize CacheManager 109 CacheManager.init(context); 110 // create CookieSyncManager with current Context 111 CookieSyncManager.createInstance(context); 112 // create PluginManager with current Context 113 PluginManager.getInstance(context); 114 } 115 AssetManager am = context.getAssets(); 116 nativeCreateFrame(w, am, proxy.getBackForwardList()); 117 118 mSettings = settings; 119 mContext = context; 120 mCallbackProxy = proxy; 121 mDatabase = WebViewDatabase.getInstance(context); 122 mWebViewCore = w; 123 124 if (WebView.LOGV_ENABLED) { 125 Log.v(LOGTAG, "BrowserFrame constructor: this=" + this); 126 } 127 } 128 129 /** 130 * Load a url from the network or the filesystem into the main frame. 131 * Following the same behaviour as Safari, javascript: URLs are not 132 * passed to the main frame, instead they are evaluated immediately. 133 * @param url The url to load. 134 */ 135 public void loadUrl(String url) { 136 mLoadInitFromJava = true; 137 if (URLUtil.isJavaScriptUrl(url)) { 138 // strip off the scheme and evaluate the string 139 stringByEvaluatingJavaScriptFromString( 140 url.substring("javascript:".length())); 141 } else { 142 nativeLoadUrl(url); 143 } 144 mLoadInitFromJava = false; 145 } 146 147 /** 148 * Load the content as if it was loaded by the provided base URL. The 149 * failUrl is used as the history entry for the load data. If null or 150 * an empty string is passed for the failUrl, then no history entry is 151 * created. 152 * 153 * @param baseUrl Base URL used to resolve relative paths in the content 154 * @param data Content to render in the browser 155 * @param mimeType Mimetype of the data being passed in 156 * @param encoding Character set encoding of the provided data. 157 * @param failUrl URL to use if the content fails to load or null. 158 */ 159 public void loadData(String baseUrl, String data, String mimeType, 160 String encoding, String failUrl) { 161 mLoadInitFromJava = true; 162 if (failUrl == null) { 163 failUrl = ""; 164 } 165 if (data == null) { 166 data = ""; 167 } 168 169 // Setup defaults for missing values. These defaults where taken from 170 // WebKit's WebFrame.mm 171 if (baseUrl == null || baseUrl.length() == 0) { 172 baseUrl = "about:blank"; 173 } 174 if (mimeType == null || mimeType.length() == 0) { 175 mimeType = "text/html"; 176 } 177 nativeLoadData(baseUrl, data, mimeType, encoding, failUrl); 178 mLoadInitFromJava = false; 179 } 180 181 /** 182 * Go back or forward the number of steps given. 183 * @param steps A negative or positive number indicating the direction 184 * and number of steps to move. 185 */ 186 public void goBackOrForward(int steps) { 187 mLoadInitFromJava = true; 188 nativeGoBackOrForward(steps); 189 mLoadInitFromJava = false; 190 } 191 192 /** 193 * native callback 194 * Report an error to an activity. 195 * @param errorCode The HTTP error code. 196 * @param description A String description. 197 * TODO: Report all errors including resource errors but include some kind 198 * of domain identifier. Change errorCode to an enum for a cleaner 199 * interface. 200 */ 201 private void reportError(final int errorCode, final String description, 202 final String failingUrl) { 203 // As this is called for the main resource and loading will be stopped 204 // after, reset the state variables. 205 resetLoadingStates(); 206 mCallbackProxy.onReceivedError(errorCode, description, failingUrl); 207 } 208 209 private void resetLoadingStates() { 210 mCommitted = true; 211 mWebViewCore.mEndScaleZoom = mFirstLayoutDone == false; 212 mFirstLayoutDone = true; 213 } 214 215 /* package */boolean committed() { 216 return mCommitted; 217 } 218 219 /* package */boolean firstLayoutDone() { 220 return mFirstLayoutDone; 221 } 222 223 /* package */int loadType() { 224 return mLoadType; 225 } 226 227 /* package */void didFirstLayout() { 228 if (!mFirstLayoutDone) { 229 mFirstLayoutDone = true; 230 // ensure {@link WebViewCore#webkitDraw} is called as we were 231 // blocking the update in {@link #loadStarted} 232 mWebViewCore.contentDraw(); 233 } 234 mWebViewCore.mEndScaleZoom = true; 235 } 236 237 /** 238 * native callback 239 * Indicates the beginning of a new load. 240 * This method will be called once for the main frame. 241 */ 242 private void loadStarted(String url, Bitmap favicon, int loadType, 243 boolean isMainFrame) { 244 mIsMainFrame = isMainFrame; 245 246 if (isMainFrame || loadType == FRAME_LOADTYPE_STANDARD) { 247 mLoadType = loadType; 248 249 if (isMainFrame) { 250 // Call onPageStarted for main frames. 251 mCallbackProxy.onPageStarted(url, favicon); 252 // as didFirstLayout() is only called for the main frame, reset 253 // mFirstLayoutDone only for the main frames 254 mFirstLayoutDone = false; 255 mCommitted = false; 256 // remove pending draw to block update until mFirstLayoutDone is 257 // set to true in didFirstLayout() 258 mWebViewCore.removeMessages(WebViewCore.EventHub.WEBKIT_DRAW); 259 } 260 261 // Note: only saves committed form data in standard load 262 if (loadType == FRAME_LOADTYPE_STANDARD 263 && mSettings.getSaveFormData()) { 264 final WebHistoryItem h = mCallbackProxy.getBackForwardList() 265 .getCurrentItem(); 266 if (h != null) { 267 String currentUrl = h.getUrl(); 268 if (currentUrl != null) { 269 mDatabase.setFormData(currentUrl, getFormTextData()); 270 } 271 } 272 } 273 } 274 } 275 276 /** 277 * native callback 278 * Indicates the WebKit has committed to the new load 279 */ 280 private void transitionToCommitted(int loadType, boolean isMainFrame) { 281 // loadType is not used yet 282 if (isMainFrame) { 283 mCommitted = true; 284 } 285 } 286 287 /** 288 * native callback 289 * <p> 290 * Indicates the end of a new load. 291 * This method will be called once for the main frame. 292 */ 293 private void loadFinished(String url, int loadType, boolean isMainFrame) { 294 // mIsMainFrame and isMainFrame are better be equal!!! 295 296 if (isMainFrame || loadType == FRAME_LOADTYPE_STANDARD) { 297 if (isMainFrame) { 298 resetLoadingStates(); 299 mCallbackProxy.switchOutDrawHistory(); 300 mCallbackProxy.onPageFinished(url); 301 } 302 } 303 } 304 305 /** 306 * We have received an SSL certificate for the main top-level page. 307 * 308 * !!!Called from the network thread!!! 309 */ 310 void certificate(SslCertificate certificate) { 311 if (mIsMainFrame) { 312 // we want to make this call even if the certificate is null 313 // (ie, the site is not secure) 314 mCallbackProxy.onReceivedCertificate(certificate); 315 } 316 } 317 318 /** 319 * Destroy all native components of the BrowserFrame. 320 */ 321 public void destroy() { 322 nativeDestroyFrame(); 323 removeCallbacksAndMessages(null); 324 } 325 326 /** 327 * Handle messages posted to us. 328 * @param msg The message to handle. 329 */ 330 @Override 331 public void handleMessage(Message msg) { 332 switch (msg.what) { 333 case FRAME_COMPLETED: { 334 if (mSettings.getSavePassword() && hasPasswordField()) { 335 if (WebView.DEBUG) { 336 Assert.assertNotNull(mCallbackProxy.getBackForwardList() 337 .getCurrentItem()); 338 } 339 WebAddress uri = new WebAddress( 340 mCallbackProxy.getBackForwardList().getCurrentItem() 341 .getUrl()); 342 String schemePlusHost = uri.mScheme + uri.mHost; 343 String[] up = mDatabase.getUsernamePassword(schemePlusHost); 344 if (up != null && up[0] != null) { 345 setUsernamePassword(up[0], up[1]); 346 } 347 } 348 CacheManager.trimCacheIfNeeded(); 349 break; 350 } 351 352 case POLICY_FUNCTION: { 353 nativeCallPolicyFunction(msg.arg1, msg.arg2); 354 break; 355 } 356 357 default: 358 break; 359 } 360 } 361 362 /** 363 * Punch-through for WebCore to set the document 364 * title. Inform the Activity of the new title. 365 * @param title The new title of the document. 366 */ 367 private void setTitle(String title) { 368 // FIXME: The activity must call getTitle (a native method) to get the 369 // title. We should try and cache the title if we can also keep it in 370 // sync with the document. 371 mCallbackProxy.onReceivedTitle(title); 372 } 373 374 /** 375 * Retrieves the render tree of this frame and puts it as the object for 376 * the message and sends the message. 377 * @param callback the message to use to send the render tree 378 */ 379 public void externalRepresentation(Message callback) { 380 callback.obj = externalRepresentation();; 381 callback.sendToTarget(); 382 } 383 384 /** 385 * Return the render tree as a string 386 */ 387 private native String externalRepresentation(); 388 389 /** 390 * Retrieves the visual text of the current frame, puts it as the object for 391 * the message and sends the message. 392 * @param callback the message to use to send the visual text 393 */ 394 public void documentAsText(Message callback) { 395 callback.obj = documentAsText();; 396 callback.sendToTarget(); 397 } 398 399 /** 400 * Return the text drawn on the screen as a string 401 */ 402 private native String documentAsText(); 403 404 /* 405 * This method is called by WebCore to inform the frame that 406 * the Javascript window object has been cleared. 407 * We should re-attach any attached js interfaces. 408 */ 409 private void windowObjectCleared(int nativeFramePointer) { 410 if (mJSInterfaceMap != null) { 411 Iterator iter = mJSInterfaceMap.keySet().iterator(); 412 while (iter.hasNext()) { 413 String interfaceName = (String) iter.next(); 414 nativeAddJavascriptInterface(nativeFramePointer, 415 mJSInterfaceMap.get(interfaceName), interfaceName); 416 } 417 } 418 } 419 420 /** 421 * This method is called by WebCore to check whether application 422 * wants to hijack url loading 423 */ 424 public boolean handleUrl(String url) { 425 if (mLoadInitFromJava == true) { 426 return false; 427 } 428 if (mCallbackProxy.shouldOverrideUrlLoading(url)) { 429 // if the url is hijacked, reset the state of the BrowserFrame 430 didFirstLayout(); 431 return true; 432 } else { 433 return false; 434 } 435 } 436 437 public void addJavascriptInterface(Object obj, String interfaceName) { 438 if (mJSInterfaceMap == null) { 439 mJSInterfaceMap = new HashMap<String, Object>(); 440 } 441 if (mJSInterfaceMap.containsKey(interfaceName)) { 442 mJSInterfaceMap.remove(interfaceName); 443 } 444 mJSInterfaceMap.put(interfaceName, obj); 445 } 446 447 /** 448 * Start loading a resource. 449 * @param loaderHandle The native ResourceLoader that is the target of the 450 * data. 451 * @param url The url to load. 452 * @param method The http method. 453 * @param headers The http headers. 454 * @param postData If the method is "POST" postData is sent as the request 455 * body. Is null when empty. 456 * @param cacheMode The cache mode to use when loading this resource. 457 * @param isHighPriority True if this resource needs to be put at the front 458 * of the network queue. 459 * @param synchronous True if the load is synchronous. 460 * @return A newly created LoadListener object. 461 */ 462 private LoadListener startLoadingResource(int loaderHandle, 463 String url, 464 String method, 465 HashMap headers, 466 byte[] postData, 467 int cacheMode, 468 boolean isHighPriority, 469 boolean synchronous) { 470 PerfChecker checker = new PerfChecker(); 471 472 if (mSettings.getCacheMode() != WebSettings.LOAD_DEFAULT) { 473 cacheMode = mSettings.getCacheMode(); 474 } 475 476 if (method.equals("POST")) { 477 // Don't use the cache on POSTs when issuing a normal POST 478 // request. 479 if (cacheMode == WebSettings.LOAD_NORMAL) { 480 cacheMode = WebSettings.LOAD_NO_CACHE; 481 } 482 if (mSettings.getSavePassword() && hasPasswordField()) { 483 try { 484 if (WebView.DEBUG) { 485 Assert.assertNotNull(mCallbackProxy.getBackForwardList() 486 .getCurrentItem()); 487 } 488 WebAddress uri = new WebAddress(mCallbackProxy 489 .getBackForwardList().getCurrentItem().getUrl()); 490 String schemePlusHost = uri.mScheme + uri.mHost; 491 String[] ret = getUsernamePassword(); 492 // Has the user entered a username/password pair and is 493 // there some POST data 494 if (ret != null && postData != null && 495 ret[0].length() > 0 && ret[1].length() > 0) { 496 // Check to see if the username & password appear in 497 // the post data (there could be another form on the 498 // page and that was posted instead. 499 String postString = new String(postData); 500 if (postString.contains(URLEncoder.encode(ret[0])) && 501 postString.contains(URLEncoder.encode(ret[1]))) { 502 String[] saved = mDatabase.getUsernamePassword( 503 schemePlusHost); 504 if (saved != null) { 505 // null username implies that user has chosen not to 506 // save password 507 if (saved[0] != null) { 508 // non-null username implies that user has 509 // chosen to save password, so update the 510 // recorded password 511 mDatabase.setUsernamePassword( 512 schemePlusHost, ret[0], ret[1]); 513 } 514 } else { 515 // CallbackProxy will handle creating the resume 516 // message 517 mCallbackProxy.onSavePassword(schemePlusHost, ret[0], 518 ret[1], null); 519 } 520 } 521 } 522 } catch (ParseException ex) { 523 // if it is bad uri, don't save its password 524 } 525 526 } 527 } 528 529 // is this resource the main-frame top-level page? 530 boolean isMainFramePage = mIsMainFrame; 531 532 if (WebView.LOGV_ENABLED) { 533 Log.v(LOGTAG, "startLoadingResource: url=" + url + ", method=" 534 + method + ", postData=" + postData + ", isHighPriority=" 535 + isHighPriority + ", isMainFramePage=" + isMainFramePage); 536 } 537 538 // Create a LoadListener 539 LoadListener loadListener = LoadListener.getLoadListener(mContext, this, url, 540 loaderHandle, synchronous, isMainFramePage); 541 542 mCallbackProxy.onLoadResource(url); 543 544 if (LoadListener.getNativeLoaderCount() > MAX_OUTSTANDING_REQUESTS) { 545 loadListener.error( 546 android.net.http.EventHandler.ERROR, mContext.getString( 547 com.android.internal.R.string.httpErrorTooManyRequests)); 548 loadListener.notifyError(); 549 loadListener.tearDown(); 550 return null; 551 } 552 553 // during synchronous load, the WebViewCore thread is blocked, so we 554 // need to endCacheTransaction first so that http thread won't be 555 // blocked in setupFile() when createCacheFile. 556 if (synchronous) { 557 CacheManager.endCacheTransaction(); 558 } 559 560 FrameLoader loader = new FrameLoader(loadListener, mSettings, 561 method, isHighPriority); 562 loader.setHeaders(headers); 563 loader.setPostData(postData); 564 // Set the load mode to the mode used for the current page. 565 // If WebKit wants validation, go to network directly. 566 loader.setCacheMode(headers.containsKey("If-Modified-Since") 567 || headers.containsKey("If-None-Match") ? 568 WebSettings.LOAD_NO_CACHE : cacheMode); 569 // Set referrer to current URL? 570 if (!loader.executeLoad()) { 571 checker.responseAlert("startLoadingResource fail"); 572 } 573 checker.responseAlert("startLoadingResource succeed"); 574 575 if (synchronous) { 576 CacheManager.startCacheTransaction(); 577 } 578 579 return !synchronous ? loadListener : null; 580 } 581 582 /** 583 * Set the progress for the browser activity. Called by native code. 584 * Uses a delay so it does not happen too often. 585 * @param newProgress An int between zero and one hundred representing 586 * the current progress percentage of loading the page. 587 */ 588 private void setProgress(int newProgress) { 589 mCallbackProxy.onProgressChanged(newProgress); 590 if (newProgress == 100) { 591 sendMessageDelayed(obtainMessage(FRAME_COMPLETED), 100); 592 } 593 // FIXME: Need to figure out a better way to switch out of the history 594 // drawing mode. Maybe we can somehow compare the history picture with 595 // the current picture, and switch when it contains more content. 596 if (mFirstLayoutDone && newProgress > TRANSITION_SWITCH_THRESHOLD) { 597 mCallbackProxy.switchOutDrawHistory(); 598 } 599 } 600 601 /** 602 * Send the icon to the activity for display. 603 * @param icon A Bitmap representing a page's favicon. 604 */ 605 private void didReceiveIcon(Bitmap icon) { 606 mCallbackProxy.onReceivedIcon(icon); 607 } 608 609 /** 610 * Request a new window from the client. 611 * @return The BrowserFrame object stored in the new WebView. 612 */ 613 private BrowserFrame createWindow(boolean dialog, boolean userGesture) { 614 WebView w = mCallbackProxy.createWindow(dialog, userGesture); 615 if (w != null) { 616 return w.getWebViewCore().getBrowserFrame(); 617 } 618 return null; 619 } 620 621 /** 622 * Try to focus this WebView. 623 */ 624 private void requestFocus() { 625 mCallbackProxy.onRequestFocus(); 626 } 627 628 /** 629 * Close this frame and window. 630 */ 631 private void closeWindow(WebViewCore w) { 632 mCallbackProxy.onCloseWindow(w.getWebView()); 633 } 634 635 // XXX: Must match PolicyAction in FrameLoaderTypes.h in webcore 636 static final int POLICY_USE = 0; 637 static final int POLICY_IGNORE = 2; 638 639 private void decidePolicyForFormResubmission(int policyFunction) { 640 Message dontResend = obtainMessage(POLICY_FUNCTION, policyFunction, 641 POLICY_IGNORE); 642 Message resend = obtainMessage(POLICY_FUNCTION, policyFunction, 643 POLICY_USE); 644 mCallbackProxy.onFormResubmission(dontResend, resend); 645 } 646 647 /** 648 * Tell the activity to update its global history. 649 */ 650 private void updateVisitedHistory(String url, boolean isReload) { 651 mCallbackProxy.doUpdateVisitedHistory(url, isReload); 652 } 653 654 /** 655 * Get the CallbackProxy for sending messages to the UI thread. 656 */ 657 /* package */ CallbackProxy getCallbackProxy() { 658 return mCallbackProxy; 659 } 660 661 /** 662 * Returns the User Agent used by this frame 663 */ 664 String getUserAgentString() { 665 return mSettings.getUserAgentString(); 666 } 667 668 // these ids need to be in sync with enum RAW_RES_ID in WebFrame 669 private static final int NODOMAIN = 1; 670 private static final int LOADERROR = 2; 671 672 String getRawResFilename(int id) { 673 int resid; 674 switch (id) { 675 case NODOMAIN: 676 resid = com.android.internal.R.raw.nodomain; 677 break; 678 679 case LOADERROR: 680 resid = com.android.internal.R.raw.loaderror; 681 break; 682 683 default: 684 Log.e(LOGTAG, "getRawResFilename got incompatible resource ID"); 685 return new String(); 686 } 687 TypedValue value = new TypedValue(); 688 mContext.getResources().getValue(resid, value, true); 689 return value.string.toString(); 690 } 691 692 //========================================================================== 693 // native functions 694 //========================================================================== 695 696 /** 697 * Create a new native frame for a given WebView 698 * @param w A WebView that the frame draws into. 699 * @param am AssetManager to use to get assets. 700 * @param list The native side will add and remove items from this list as 701 * the native list changes. 702 */ 703 private native void nativeCreateFrame(WebViewCore w, AssetManager am, 704 WebBackForwardList list); 705 706 /** 707 * Destroy the native frame. 708 */ 709 public native void nativeDestroyFrame(); 710 711 private native void nativeCallPolicyFunction(int policyFunction, 712 int decision); 713 714 /** 715 * Reload the current main frame. 716 */ 717 public native void reload(boolean allowStale); 718 719 /** 720 * Go back or forward the number of steps given. 721 * @param steps A negative or positive number indicating the direction 722 * and number of steps to move. 723 */ 724 private native void nativeGoBackOrForward(int steps); 725 726 /** 727 * stringByEvaluatingJavaScriptFromString will execute the 728 * JS passed in in the context of this browser frame. 729 * @param script A javascript string to execute 730 * 731 * @return string result of execution or null 732 */ 733 public native String stringByEvaluatingJavaScriptFromString(String script); 734 735 /** 736 * Add a javascript interface to the main frame. 737 */ 738 private native void nativeAddJavascriptInterface(int nativeFramePointer, 739 Object obj, String interfaceName); 740 741 /** 742 * Enable or disable the native cache. 743 */ 744 /* FIXME: The native cache is always on for now until we have a better 745 * solution for our 2 caches. */ 746 private native void setCacheDisabled(boolean disabled); 747 748 public native boolean cacheDisabled(); 749 750 public native void clearCache(); 751 752 /** 753 * Returns false if the url is bad. 754 */ 755 private native void nativeLoadUrl(String url); 756 757 private native void nativeLoadData(String baseUrl, String data, 758 String mimeType, String encoding, String failUrl); 759 760 /** 761 * Stop loading the current page. 762 */ 763 public void stopLoading() { 764 if (mIsMainFrame) { 765 resetLoadingStates(); 766 } 767 nativeStopLoading(); 768 } 769 770 private native void nativeStopLoading(); 771 772 /** 773 * Return true if the document has images. 774 */ 775 public native boolean documentHasImages(); 776 777 /** 778 * @return TRUE if there is a password field in the current frame 779 */ 780 private native boolean hasPasswordField(); 781 782 /** 783 * Get username and password in the current frame. If found, String[0] is 784 * username and String[1] is password. Otherwise return NULL. 785 * @return String[] 786 */ 787 private native String[] getUsernamePassword(); 788 789 /** 790 * Set username and password to the proper fields in the current frame 791 * @param username 792 * @param password 793 */ 794 private native void setUsernamePassword(String username, String password); 795 796 /** 797 * Get form's "text" type data associated with the current frame. 798 * @return HashMap If succeed, returns a list of name/value pair. Otherwise 799 * returns null. 800 */ 801 private native HashMap getFormTextData(); 802} 803