1 /* 2 * Copyright 2006, The Android Open Source Project 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #ifndef WEBVIEWCORE_H 27 #define WEBVIEWCORE_H 28 29 #include "android_npapi.h" 30 #include "FileChooser.h" 31 #include "CacheBuilder.h" 32 #include "CachedHistory.h" 33 #include "PictureSet.h" 34 #include "PlatformGraphicsContext.h" 35 #include "SkColor.h" 36 #include "SkTDArray.h" 37 #include "SkRegion.h" 38 #include "Timer.h" 39 #include "WebCoreRefObject.h" 40 #include "WebCoreJni.h" 41 #include <jni.h> 42 #include <ui/KeycodeLabels.h> 43 #include <ui/PixelFormat.h> 44 45 namespace WebCore { 46 class AtomicString; 47 class Color; 48 class FrameView; 49 class HTMLAnchorElement; 50 class HTMLSelectElement; 51 class RenderPart; 52 class RenderText; 53 class Node; 54 class PlatformKeyboardEvent; 55 class RenderTextControl; 56 class ScrollView; 57 class TimerBase; 58 class PageGroup; 59 } 60 61 #if USE(ACCELERATED_COMPOSITING) 62 namespace WebCore { 63 class GraphicsLayerAndroid; 64 class LayerAndroid; 65 } 66 #endif 67 68 struct PluginWidgetAndroid; 69 class SkPicture; 70 class SkIRect; 71 72 namespace android { 73 74 class CachedFrame; 75 class CachedNode; 76 class CachedRoot; 77 class ListBoxReply; 78 79 class WebCoreReply : public WebCoreRefObject { 80 public: ~WebCoreReply()81 virtual ~WebCoreReply() {} 82 replyInt(int value)83 virtual void replyInt(int value) { 84 SkDEBUGF(("WebCoreReply::replyInt(%d) not handled\n", value)); 85 } 86 replyIntArray(const int * array,int count)87 virtual void replyIntArray(const int* array, int count) { 88 SkDEBUGF(("WebCoreReply::replyIntArray() not handled\n")); 89 } 90 // add more replyFoo signatures as needed 91 }; 92 93 // one instance of WebViewCore per page for calling into Java's WebViewCore 94 class WebViewCore : public WebCoreRefObject { 95 public: 96 /** 97 * Initialize the native WebViewCore with a JNI environment, a Java 98 * WebViewCore object and the main frame. 99 */ 100 WebViewCore(JNIEnv* env, jobject javaView, WebCore::Frame* mainframe); 101 ~WebViewCore(); 102 103 // helper function 104 static WebViewCore* getWebViewCore(const WebCore::FrameView* view); 105 static WebViewCore* getWebViewCore(const WebCore::ScrollView* view); 106 107 // Followings are called from native WebCore to Java 108 109 /** 110 * Scroll to an absolute position. 111 * @param x The x coordinate. 112 * @param y The y coordinate. 113 * @param animate If it is true, animate to the new scroll position 114 * 115 * This method calls Java to trigger a gradual scroll event. 116 */ 117 void scrollTo(int x, int y, bool animate = false); 118 119 /** 120 * Scroll to the point x,y relative to the current position. 121 * @param x The relative x position. 122 * @param y The relative y position. 123 * @param animate If it is true, animate to the new scroll position 124 */ 125 void scrollBy(int x, int y, bool animate); 126 127 /** 128 * Record the invalid rectangle 129 */ 130 void contentInvalidate(const WebCore::IntRect &rect); 131 132 /** 133 * Satisfy any outstanding invalidates, so that the current state 134 * of the DOM is drawn. 135 */ 136 void contentDraw(); 137 138 #if USE(ACCELERATED_COMPOSITING) 139 GraphicsLayerAndroid* graphicsRootLayer() const; 140 void immediateRepaint(); 141 void setUIRootLayer(const LayerAndroid* layer); 142 #endif 143 144 /** Invalidate the view/screen, NOT the content/DOM, but expressed in 145 * content/DOM coordinates (i.e. they need to eventually be scaled, 146 * by webview into view.java coordinates 147 */ 148 void viewInvalidate(const WebCore::IntRect& rect); 149 150 /** 151 * Invalidate part of the content that may be offscreen at the moment 152 */ 153 void offInvalidate(const WebCore::IntRect &rect); 154 155 /** 156 * Called by webcore when the progress indicator is done 157 * used to rebuild and display any changes in focus 158 */ 159 void notifyProgressFinished(); 160 161 /** 162 * Notify the view that WebCore did its first layout. 163 */ 164 void didFirstLayout(); 165 166 /** 167 * Notify the view to update the viewport. 168 */ 169 void updateViewport(); 170 171 /** 172 * Notify the view to restore the screen width, which in turn restores 173 * the scale. 174 */ 175 void restoreScale(int); 176 177 /** 178 * Notify the view to restore the scale used to calculate the screen 179 * width for wrapping the text 180 */ 181 void restoreScreenWidthScale(int); 182 183 /** 184 * Tell the java side to update the focused textfield 185 * @param pointer Pointer to the node for the input field. 186 * @param changeToPassword If true, we are changing the textfield to 187 * a password field, and ignore the String 188 * @param text If changeToPassword is false, this is the new text that 189 * should go into the textfield. 190 */ 191 void updateTextfield(WebCore::Node* pointer, 192 bool changeToPassword, const WebCore::String& text); 193 194 /** 195 * Tell the java side to update the current selection in the focused 196 * textfield to the WebTextView. This function finds the currently 197 * focused textinput, and passes its selection to java. 198 * If there is no focus, or it is not a text input, this does nothing. 199 */ 200 void updateTextSelection(); 201 202 void clearTextEntry(); 203 // JavaScript support 204 void jsAlert(const WebCore::String& url, const WebCore::String& text); 205 bool jsConfirm(const WebCore::String& url, const WebCore::String& text); 206 bool jsPrompt(const WebCore::String& url, const WebCore::String& message, 207 const WebCore::String& defaultValue, WebCore::String& result); 208 bool jsUnload(const WebCore::String& url, const WebCore::String& message); 209 bool jsInterrupt(); 210 211 /** 212 * Tell the Java side that the origin has exceeded its database quota. 213 * @param url The URL of the page that caused the quota overflow 214 * @param databaseIdentifier the id of the database that caused the 215 * quota overflow. 216 * @param currentQuota The current quota for the origin 217 * @param estimatedSize The estimated size of the database 218 */ 219 void exceededDatabaseQuota(const WebCore::String& url, 220 const WebCore::String& databaseIdentifier, 221 const unsigned long long currentQuota, 222 const unsigned long long estimatedSize); 223 224 /** 225 * Tell the Java side that the appcache has exceeded its max size. 226 * @param spaceNeeded is the amount of disk space that would be needed 227 * in order for the last appcache operation to succeed. 228 */ 229 void reachedMaxAppCacheSize(const unsigned long long spaceNeeded); 230 231 /** 232 * Set up the PageGroup's idea of which links have been visited, 233 * with the browser history. 234 * @param group the object to deliver the links to. 235 */ 236 void populateVisitedLinks(WebCore::PageGroup*); 237 238 /** 239 * Instruct the browser to show a Geolocation permission prompt for the 240 * specified origin. 241 * @param origin The origin of the frame requesting Geolocation 242 * permissions. 243 */ 244 void geolocationPermissionsShowPrompt(const WebCore::String& origin); 245 /** 246 * Instruct the browser to hide the Geolocation permission prompt. 247 */ 248 void geolocationPermissionsHidePrompt(); 249 250 void addMessageToConsole(const String& message, unsigned int lineNumber, const String& sourceID, int msgLevel); 251 252 /** 253 * Tell the Java side of the scrollbar mode 254 */ 255 void setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode verticalMode); 256 257 // 258 // Followings support calls from Java to native WebCore 259 // 260 261 262 WebCore::String retrieveHref(WebCore::Frame* frame, WebCore::Node* node); 263 WebCore::String retrieveAnchorText(WebCore::Frame* frame, WebCore::Node* node); 264 WebCore::String requestLabel(WebCore::Frame* , WebCore::Node* ); 265 266 // Create a single picture to represent the drawn DOM (used by navcache) 267 void recordPicture(SkPicture* picture); 268 269 // Create a set of pictures to represent the drawn DOM, driven by 270 // the invalidated region and the time required to draw (used to draw) 271 void recordPictureSet(PictureSet* master); 272 void moveFocus(WebCore::Frame* frame, WebCore::Node* node); 273 void moveMouse(WebCore::Frame* frame, int x, int y); 274 void moveMouseIfLatest(int moveGeneration, 275 WebCore::Frame* frame, int x, int y); 276 277 // set the scroll amount that webview.java is currently showing 278 void setScrollOffset(int moveGeneration, int dx, int dy); 279 280 void setGlobalBounds(int x, int y, int h, int v); 281 282 void setSizeScreenWidthAndScale(int width, int height, int screenWidth, 283 float scale, int realScreenWidth, int screenHeight, int anchorX, 284 int anchorY, bool ignoreHeight); 285 286 /** 287 * Handle key events from Java. 288 * @return Whether keyCode was handled by this class. 289 */ 290 bool key(const WebCore::PlatformKeyboardEvent& event); 291 292 /** 293 * Handle (trackball) click event from Java 294 */ 295 void click(WebCore::Frame* frame, WebCore::Node* node); 296 297 /** 298 * Handle touch event 299 */ 300 bool handleTouchEvent(int action, int x, int y, int metaState); 301 302 /** 303 * Handle motionUp event from the UI thread (called touchUp in the 304 * WebCore thread). 305 */ 306 void touchUp(int touchGeneration, WebCore::Frame* frame, 307 WebCore::Node* node, int x, int y); 308 309 /** 310 * Sets the index of the label from a popup 311 */ 312 void popupReply(int index); 313 void popupReply(const int* array, int count); 314 315 /** 316 * Delete text from start to end in the focused textfield. 317 * If start == end, set the selection, but perform no deletion. 318 * If there is no focus, silently fail. 319 * If start and end are out of order, swap them. 320 */ 321 void deleteSelection(int start, int end, int textGeneration); 322 323 /** 324 * Set the selection of the currently focused textfield to (start, end). 325 * If start and end are out of order, swap them. 326 */ 327 void setSelection(int start, int end); 328 /** 329 * In the currently focused textfield, replace the characters from oldStart to oldEnd 330 * (if oldStart == oldEnd, this will be an insert at that position) with replace, 331 * and set the selection to (start, end). 332 */ 333 void replaceTextfieldText(int oldStart, 334 int oldEnd, const WebCore::String& replace, int start, int end, 335 int textGeneration); 336 void passToJs(int generation, 337 const WebCore::String& , const WebCore::PlatformKeyboardEvent& ); 338 /** 339 * Scroll the focused textfield to (x, y) in document space 340 */ 341 void scrollFocusedTextInput(float x, int y); 342 /** 343 * Set the FocusController's active and focused states, so that 344 * the caret will draw (true) or not. 345 */ 346 void setFocusControllerActive(WebCore::Frame*, bool active); 347 348 void saveDocumentState(WebCore::Frame* frame); 349 350 void addVisitedLink(const UChar*, int); 351 352 // TODO: I don't like this hack but I need to access the java object in 353 // order to send it as a parameter to java 354 AutoJObject getJavaObject(); 355 356 // Return the parent WebView Java object associated with this 357 // WebViewCore. 358 jobject getWebViewJavaObject(); 359 360 void setBackgroundColor(SkColor c); 361 void updateFrameCache(); 362 void updateCacheOnNodeChange(); 363 void dumpDomTree(bool); 364 void dumpRenderTree(bool); 365 void dumpNavTree(); 366 367 /* We maintain a list of active plugins. The list is edited by the 368 pluginview itself. The list is used to service invals to the plugin 369 pageflipping bitmap. 370 */ 371 void addPlugin(PluginWidgetAndroid*); 372 void removePlugin(PluginWidgetAndroid*); 373 // returns true if the pluginwidgit is in our active list 374 bool isPlugin(PluginWidgetAndroid*) const; 375 void invalPlugin(PluginWidgetAndroid*); 376 void drawPlugins(); 377 378 // send the current screen size/zoom to all of the plugins in our list 379 void sendPluginVisibleScreen(); 380 381 // send onLoad event to plugins who are descendents of the given frame 382 void notifyPluginsOnFrameLoad(const Frame*); 383 384 // send this event to all of the plugins in our list 385 void sendPluginEvent(const ANPEvent&); 386 387 // lookup the plugin widget struct given an NPP 388 PluginWidgetAndroid* getPluginWidget(NPP npp); 389 390 // return the cursorNode if it is a plugin 391 Node* cursorNodeIsPlugin(); 392 393 // Notify the Java side whether it needs to pass down the touch events 394 void needTouchEvents(bool); 395 396 void requestKeyboardWithSelection(const WebCore::Node*, int selStart, int selEnd); 397 // Notify the Java side that webkit is requesting a keyboard 398 void requestKeyboard(bool showKeyboard); 399 400 // Generates a class loader that contains classes from the plugin's apk 401 jclass getPluginClass(const WebCore::String& libName, const char* className); 402 403 // Creates a full screen surface for a plugin 404 void showFullScreenPlugin(jobject webkitPlugin, NPP npp); 405 406 // Instructs the UI thread to discard the plugin's full-screen surface 407 void hideFullScreenPlugin(); 408 409 // Adds the plugin's view (aka surface) to the view hierarchy 410 jobject addSurface(jobject view, int x, int y, int width, int height); 411 412 // Updates a Surface coordinates and dimensions for a plugin 413 void updateSurface(jobject childView, int x, int y, int width, int height); 414 415 // Destroys a SurfaceView for a plugin 416 void destroySurface(jobject childView); 417 418 // Returns the context (android.content.Context) of the WebView 419 jobject getContext(); 420 421 bool validNodeAndBounds(Frame* , Node* , const IntRect& ); 422 423 // Make the rect (left, top, width, height) visible. If it can be fully 424 // fit, center it on the screen. Otherwise make sure the point specified 425 // by (left + xPercentInDoc * width, top + yPercentInDoc * height) 426 // pinned at the screen position (xPercentInView, yPercentInView). 427 void showRect(int left, int top, int width, int height, int contentWidth, 428 int contentHeight, float xPercentInDoc, float xPercentInView, 429 float yPercentInDoc, float yPercentInView); 430 431 // Scale the rect (x, y, width, height) to make it just fit and centered 432 // in the current view. 433 void centerFitRect(int x, int y, int width, int height); 434 435 // other public functions 436 public: 437 // Open a file chooser for selecting a file to upload 438 void openFileChooser(PassRefPtr<WebCore::FileChooser> ); 439 440 // reset the picture set to empty 441 void clearContent(); 442 443 // flatten the picture set to a picture 444 void copyContentToPicture(SkPicture* ); 445 446 // draw the picture set with the specified background color 447 bool drawContent(SkCanvas* , SkColor ); 448 bool focusBoundsChanged(); 449 bool pictureReady(); 450 451 // record the inval area, and the picture size 452 bool recordContent(SkRegion* , SkIPoint* ); screenWidth()453 int screenWidth() const { return m_screenWidth; } screenHeight()454 int screenHeight() const { return m_screenHeight; } scale()455 float scale() const { return m_scale; } screenWidthScale()456 float screenWidthScale() const { return m_screenWidthScale; } mainFrame()457 WebCore::Frame* mainFrame() const { return m_mainFrame; } 458 void updateCursorBounds(const CachedRoot* root, 459 const CachedFrame* cachedFrame, const CachedNode* cachedNode); 460 void updateFrameCacheIfLoading(); 461 462 // utility to split slow parts of the picture set 463 void splitContent(); 464 465 // these members are shared with webview.cpp 466 static Mutex gFrameCacheMutex; 467 CachedRoot* m_frameCacheKit; // nav data being built by webcore 468 SkPicture* m_navPictureKit; 469 int m_moveGeneration; // copy of state in WebViewNative triggered by move 470 int m_touchGeneration; // copy of state in WebViewNative triggered by touch 471 int m_lastGeneration; // last action using up to date cache 472 bool m_updatedFrameCache; 473 bool m_findIsUp; 474 bool m_hasCursorBounds; 475 WebCore::IntRect m_cursorBounds; 476 WebCore::IntRect m_cursorHitBounds; 477 void* m_cursorFrame; 478 IntPoint m_cursorLocation; 479 void* m_cursorNode; 480 static Mutex gCursorBoundsMutex; 481 // These two fields go together: we use the mutex to protect access to 482 // m_buttons, so that we, and webview.cpp can look/modify the m_buttons 483 // field safely from our respective threads 484 static Mutex gButtonMutex; 485 WTF::Vector<Container> m_buttons; isPaused()486 bool isPaused() const { return m_isPaused; } setIsPaused(bool isPaused)487 void setIsPaused(bool isPaused) { m_isPaused = isPaused; } 488 // end of shared members 489 490 // internal functions 491 private: 492 CacheBuilder& cacheBuilder(); 493 WebCore::Node* currentFocus(); 494 // Compare the new set of buttons to the old one. All of the new 495 // buttons either replace our old ones or should be added to our list. 496 // Then check the old buttons to see if any are no longer needed. 497 void updateButtonList(WTF::Vector<Container>* buttons); 498 void reset(bool fromConstructor); 499 500 void listBoxRequest(WebCoreReply* reply, const uint16_t** labels, 501 size_t count, const int enabled[], size_t enabledCount, 502 bool multiple, const int selected[], size_t selectedCountOrSelection); 503 504 friend class ListBoxReply; 505 struct JavaGlue; 506 struct JavaGlue* m_javaGlue; 507 WebCore::Frame* m_mainFrame; 508 WebCoreReply* m_popupReply; 509 WebCore::Node* m_lastFocused; 510 WebCore::IntRect m_lastFocusedBounds; 511 int m_lastFocusedSelStart; 512 int m_lastFocusedSelEnd; 513 static Mutex m_contentMutex; // protects ui/core thread pictureset access 514 PictureSet m_content; // the set of pictures to draw (accessed by UI too) 515 SkRegion m_addInval; // the accumulated inval region (not yet drawn) 516 SkRegion m_rebuildInval; // the accumulated region for rebuilt pictures 517 // Used in passToJS to avoid updating the UI text field until after the 518 // key event has been processed. 519 bool m_blockTextfieldUpdates; 520 bool m_focusBoundsChanged; 521 bool m_skipContentDraw; 522 // Passed in with key events to know when they were generated. Store it 523 // with the cache so that we can ignore stale text changes. 524 int m_textGeneration; 525 CachedRoot* m_temp; 526 SkPicture* m_tempPict; 527 int m_maxXScroll; 528 int m_maxYScroll; 529 int m_scrollOffsetX; // webview.java's current scroll in X 530 int m_scrollOffsetY; // webview.java's current scroll in Y 531 WebCore::IntPoint m_mousePos; 532 bool m_frameCacheOutOfDate; 533 bool m_progressDone; 534 int m_lastPassed; 535 int m_lastVelocity; 536 CachedHistory m_history; 537 int m_screenWidth; // width of the visible rect in document coordinates 538 int m_screenHeight;// height of the visible rect in document coordinates 539 float m_scale; 540 float m_screenWidthScale; 541 unsigned m_domtree_version; 542 bool m_check_domtree_version; 543 PageGroup* m_groupForVisitedLinks; 544 bool m_isPaused; 545 546 SkTDArray<PluginWidgetAndroid*> m_plugins; 547 WebCore::Timer<WebViewCore> m_pluginInvalTimer; pluginInvalTimerFired(WebCore::Timer<WebViewCore> *)548 void pluginInvalTimerFired(WebCore::Timer<WebViewCore>*) { 549 this->drawPlugins(); 550 } 551 552 void doMaxScroll(CacheBuilder::Direction dir); 553 SkPicture* rebuildPicture(const SkIRect& inval); 554 void rebuildPictureSet(PictureSet* ); 555 void sendNotifyProgressFinished(); 556 bool handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* nodePtr); 557 WebCore::HTMLAnchorElement* retrieveAnchorElement(WebCore::Frame* frame, WebCore::Node* node); 558 559 #if ENABLE(TOUCH_EVENTS) 560 bool m_forwardingTouchEvents; 561 IntPoint m_lastTouchPoint; 562 #endif 563 564 #if DEBUG_NAV_UI 565 uint32_t m_now; 566 #endif 567 568 private: 569 // called from constructor, to add this to a global list 570 static void addInstance(WebViewCore*); 571 // called from destructor, to remove this from a global list 572 static void removeInstance(WebViewCore*); 573 public: 574 // call only from webkit thread (like add/remove), return true if inst 575 // is still alive 576 static bool isInstance(WebViewCore*); 577 578 // if there exists at least on WebViewCore instance then we return the 579 // application context, otherwise NULL is returned. 580 static jobject getApplicationContext(); 581 582 // Check whether a media mimeType is supported in Android media framework. 583 static bool supportsMimeType(const WebCore::String& mimeType); 584 }; 585 586 } // namespace android 587 588 #endif // WEBVIEWCORE_H 589