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 APPLE COMPUTER, INC. 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 "CacheBuilder.h" 31 #include "CachedHistory.h" 32 #include "PictureSet.h" 33 #include "PlatformGraphicsContext.h" 34 #include "SkColor.h" 35 #include "SkTDArray.h" 36 #include "SkRegion.h" 37 #include "Timer.h" 38 #include "WebCoreRefObject.h" 39 #include "WebCoreJni.h" 40 #include <jni.h> 41 #include <ui/KeycodeLabels.h> 42 #include <ui/PixelFormat.h> 43 44 namespace WebCore { 45 class AtomicString; 46 class Color; 47 class FrameView; 48 class HTMLSelectElement; 49 class RenderPart; 50 class RenderText; 51 class Node; 52 class PlatformKeyboardEvent; 53 class RenderTextControl; 54 class ScrollView; 55 class TimerBase; 56 class PageGroup; 57 } 58 59 struct PluginWidgetAndroid; 60 class SkPicture; 61 class SkIRect; 62 63 namespace android { 64 65 enum PluginState { 66 kGainFocus_PluginState = 0, 67 kLoseFocus_PluginState = 1, 68 }; 69 70 class CachedRoot; 71 class ListBoxReply; 72 class SurfaceCallback; 73 74 class WebCoreReply : public WebCoreRefObject { 75 public: ~WebCoreReply()76 virtual ~WebCoreReply() {} 77 replyInt(int value)78 virtual void replyInt(int value) { 79 SkDEBUGF(("WebCoreReply::replyInt(%d) not handled\n", value)); 80 } 81 replyIntArray(const int * array,int count)82 virtual void replyIntArray(const int* array, int count) { 83 SkDEBUGF(("WebCoreReply::replyIntArray() not handled\n")); 84 } 85 // add more replyFoo signatures as needed 86 }; 87 88 // one instance of WebViewCore per page for calling into Java's WebViewCore 89 class WebViewCore : public WebCoreRefObject { 90 public: 91 /** 92 * Initialize the native WebViewCore with a JNI environment, a Java 93 * WebViewCore object and the main frame. 94 */ 95 WebViewCore(JNIEnv* env, jobject javaView, WebCore::Frame* mainframe); 96 ~WebViewCore(); 97 98 // helper function 99 static WebViewCore* getWebViewCore(const WebCore::FrameView* view); 100 static WebViewCore* getWebViewCore(const WebCore::ScrollView* view); 101 102 // Followings are called from native WebCore to Java 103 104 /** 105 * Scroll to an absolute position. 106 * @param x The x coordinate. 107 * @param y The y coordinate. 108 * @param animate If it is true, animate to the new scroll position 109 * 110 * This method calls Java to trigger a gradual scroll event. 111 */ 112 void scrollTo(int x, int y, bool animate = false); 113 114 /** 115 * Scroll to the point x,y relative to the current position. 116 * @param x The relative x position. 117 * @param y The relative y position. 118 * @param animate If it is true, animate to the new scroll position 119 */ 120 void scrollBy(int x, int y, bool animate); 121 122 /** 123 * Record the invalid rectangle 124 */ 125 void contentInvalidate(const WebCore::IntRect &rect); 126 127 /** 128 * Satisfy any outstanding invalidates, so that the current state 129 * of the DOM is drawn. 130 */ 131 void contentDraw(); 132 133 /** Invalidate the view/screen, NOT the content/DOM, but expressed in 134 * content/DOM coordinates (i.e. they need to eventually be scaled, 135 * by webview into view.java coordinates 136 */ 137 void viewInvalidate(const WebCore::IntRect& rect); 138 139 /** 140 * Invalidate part of the content that may be offscreen at the moment 141 */ 142 void offInvalidate(const WebCore::IntRect &rect); 143 144 /** 145 * Called by webcore when the progress indicator is done 146 * used to rebuild and display any changes in focus 147 */ 148 void notifyProgressFinished(); 149 150 /** 151 * Notify the view that WebCore did its first layout. 152 */ 153 void didFirstLayout(); 154 155 /** 156 * Notify the view to update the viewport. 157 */ 158 void updateViewport(); 159 160 /** 161 * Notify the view to restore the screen width, which in turn restores 162 * the scale. 163 */ 164 void restoreScale(int); 165 166 /** 167 * Notify the view to restore the scale used to calculate the screen 168 * width for wrapping the text 169 */ 170 void restoreScreenWidthScale(int); 171 172 /** 173 * Tell the java side to update the focused textfield 174 * @param pointer Pointer to the node for the input field. 175 * @param changeToPassword If true, we are changing the textfield to 176 * a password field, and ignore the String 177 * @param text If changeToPassword is false, this is the new text that 178 * should go into the textfield. 179 */ 180 void updateTextfield(WebCore::Node* pointer, 181 bool changeToPassword, const WebCore::String& text); 182 183 /** 184 * Tell the java side to update the current selection in the focused 185 * textfield to the WebTextView. This function finds the currently 186 * focused textinput, and passes its selection to java. 187 * If there is no focus, or it is not a text input, this does nothing. 188 */ 189 void updateTextSelection(); 190 191 void clearTextEntry(); 192 // JavaScript support 193 void jsAlert(const WebCore::String& url, const WebCore::String& text); 194 bool jsConfirm(const WebCore::String& url, const WebCore::String& text); 195 bool jsPrompt(const WebCore::String& url, const WebCore::String& message, 196 const WebCore::String& defaultValue, WebCore::String& result); 197 bool jsUnload(const WebCore::String& url, const WebCore::String& message); 198 bool jsInterrupt(); 199 200 /** 201 * Tell the Java side that the origin has exceeded its database quota. 202 * @param url The URL of the page that caused the quota overflow 203 * @param databaseIdentifier the id of the database that caused the 204 * quota overflow. 205 * @param currentQuota The current quota for the origin 206 * @param estimatedSize The estimated size of the database 207 */ 208 void exceededDatabaseQuota(const WebCore::String& url, 209 const WebCore::String& databaseIdentifier, 210 const unsigned long long currentQuota, 211 const unsigned long long estimatedSize); 212 213 /** 214 * Tell the Java side that the appcache has exceeded its max size. 215 * @param spaceNeeded is the amount of disk space that would be needed 216 * in order for the last appcache operation to succeed. 217 */ 218 void reachedMaxAppCacheSize(const unsigned long long spaceNeeded); 219 220 /** 221 * Set up the PageGroup's idea of which links have been visited, 222 * with the browser history. 223 * @param group the object to deliver the links to. 224 */ 225 void populateVisitedLinks(WebCore::PageGroup*); 226 227 /** 228 * Instruct the browser to show a Geolocation permission prompt for the 229 * specified origin. 230 * @param origin The origin of the frame requesting Geolocation 231 * permissions. 232 */ 233 void geolocationPermissionsShowPrompt(const WebCore::String& origin); 234 /** 235 * Instruct the browser to hide the Geolocation permission prompt. 236 */ 237 void geolocationPermissionsHidePrompt(); 238 239 void addMessageToConsole(const String& message, unsigned int lineNumber, const String& sourceID); 240 241 // 242 // Followings support calls from Java to native WebCore 243 // 244 245 WebCore::String retrieveHref(WebCore::Frame* frame, WebCore::Node* node); 246 247 WebCore::String getSelection(SkRegion* ); 248 249 // Create a single picture to represent the drawn DOM (used by navcache) 250 void recordPicture(SkPicture* picture); 251 252 // Create a set of pictures to represent the drawn DOM, driven by 253 // the invalidated region and the time required to draw (used to draw) 254 void recordPictureSet(PictureSet* master); 255 void moveMouse(WebCore::Frame* frame, int x, int y); 256 void moveMouseIfLatest(int moveGeneration, 257 WebCore::Frame* frame, int x, int y); 258 259 // set the scroll amount that webview.java is currently showing 260 void setScrollOffset(int moveGeneration, int dx, int dy); 261 262 void setGlobalBounds(int x, int y, int h, int v); 263 264 void setSizeScreenWidthAndScale(int width, int height, int screenWidth, 265 float scale, int realScreenWidth, int screenHeight, 266 bool ignoreHeight); 267 268 /** 269 * Handle key events from Java. 270 * @return Whether keyCode was handled by this class. 271 */ 272 bool key(const WebCore::PlatformKeyboardEvent& event); 273 274 /** 275 * Handle (trackball) click event from Java 276 */ 277 void click(WebCore::Frame* frame, WebCore::Node* node); 278 279 /** 280 * Handle touch event 281 */ 282 bool handleTouchEvent(int action, int x, int y); 283 284 /** 285 * Handle motionUp event from the UI thread (called touchUp in the 286 * WebCore thread). 287 */ 288 void touchUp(int touchGeneration, WebCore::Frame* frame, 289 WebCore::Node* node, int x, int y); 290 291 /** 292 * Sets the index of the label from a popup 293 */ 294 void popupReply(int index); 295 void popupReply(const int* array, int count); 296 297 /** 298 * Delete text from start to end in the focused textfield. 299 * If start == end, set the selection, but perform no deletion. 300 * If there is no focus, silently fail. 301 * If start and end are out of order, swap them. 302 */ 303 void deleteSelection(int start, int end, int textGeneration); 304 305 /** 306 * Set the selection of the currently focused textfield to (start, end). 307 * If start and end are out of order, swap them. 308 */ 309 void setSelection(int start, int end); 310 /** 311 * In the currently focused textfield, replace the characters from oldStart to oldEnd 312 * (if oldStart == oldEnd, this will be an insert at that position) with replace, 313 * and set the selection to (start, end). 314 */ 315 void replaceTextfieldText(int oldStart, 316 int oldEnd, const WebCore::String& replace, int start, int end, 317 int textGeneration); 318 void passToJs(int generation, 319 const WebCore::String& , const WebCore::PlatformKeyboardEvent& ); 320 /** 321 * Scroll the focused textfield to (x, y) in document space 322 */ 323 void scrollFocusedTextInput(float x, int y); 324 void setFocusControllerActive(bool active); 325 326 void saveDocumentState(WebCore::Frame* frame); 327 328 void addVisitedLink(const UChar*, int); 329 330 // TODO: I don't like this hack but I need to access the java object in 331 // order to send it as a parameter to java 332 AutoJObject getJavaObject(); 333 334 // Return the parent WebView Java object associated with this 335 // WebViewCore. 336 jobject getWebViewJavaObject(); 337 338 void setBackgroundColor(SkColor c); 339 void updateFrameCache(); 340 void updateCacheOnNodeChange(); 341 void dumpDomTree(bool); 342 void dumpRenderTree(bool); 343 void dumpNavTree(); 344 345 /* We maintain a list of active plugins. The list is edited by the 346 pluginview itself. The list is used to service invals to the plugin 347 pageflipping bitmap. 348 */ 349 void addPlugin(PluginWidgetAndroid*); 350 void removePlugin(PluginWidgetAndroid*); 351 void invalPlugin(PluginWidgetAndroid*); 352 void drawPlugins(); 353 354 // send the current screen size/zoom to all of the plugins in our list 355 void sendPluginVisibleScreen(); 356 357 // send onLoad event to plugins who are descendents of the given frame 358 void notifyPluginsOnFrameLoad(const Frame*); 359 360 // send this event to all of the plugins in our list 361 void sendPluginEvent(const ANPEvent&); 362 363 // send this event to all of the plugins who have the given flag set 364 void sendPluginEvent(const ANPEvent& evt, ANPEventFlag flag); 365 366 // return the cursorNode if it is a plugin 367 Node* cursorNodeIsPlugin(); 368 369 // notify the plugin of an update in state 370 void updatePluginState(Frame* frame, Node* node, PluginState state); 371 372 // Notify the Java side whether it needs to pass down the touch events 373 void needTouchEvents(bool); 374 375 // Notify the Java side that webkit is requesting a keyboard 376 void requestKeyboard(bool); 377 378 // Creates a full screen surface (i.e. View on an Activity) for a plugin 379 void startFullScreenPluginActivity(const char* libName, 380 const char* className, NPP npp); 381 382 // Creates a Surface (i.e. View) for a plugin 383 jobject createSurface(const char* libName, const char* className, 384 NPP npp, int x, int y, int width, int height); 385 386 // Destroys a SurfaceView for a plugin 387 void destroySurface(jobject childView); 388 389 // other public functions 390 public: 391 // reset the picture set to empty 392 void clearContent(); 393 394 // flatten the picture set to a picture 395 void copyContentToPicture(SkPicture* ); 396 397 // draw the picture set with the specified background color 398 bool drawContent(SkCanvas* , SkColor ); 399 bool pictureReady(); 400 401 // record the inval area, and the picture size 402 bool recordContent(SkRegion* , SkIPoint* ); screenWidth()403 int screenWidth() const { return m_screenWidth; } scale()404 float scale() const { return m_scale; } screenWidthScale()405 float screenWidthScale() const { return m_screenWidthScale; } mainFrame()406 WebCore::Frame* mainFrame() const { return m_mainFrame; } 407 void updateFrameCacheIfLoading(); 408 409 // utility to split slow parts of the picture set 410 void splitContent(); 411 412 // these members are shared with webview.cpp 413 static Mutex gFrameCacheMutex; 414 CachedRoot* m_frameCacheKit; // nav data being built by webcore 415 SkPicture* m_navPictureKit; 416 int m_generation; // copy of the number bumped by WebViewNative 417 int m_moveGeneration; // copy of state in WebViewNative triggered by move 418 int m_touchGeneration; // copy of state in WebViewNative triggered by touch 419 int m_lastGeneration; // last action using up to date cache 420 bool m_updatedFrameCache; 421 bool m_findIsUp; 422 bool m_hasCursorBounds; 423 WebCore::IntRect m_cursorBounds; 424 WebCore::IntRect m_cursorHitBounds; 425 void* m_cursorFrame; 426 IntPoint m_cursorLocation; 427 void* m_cursorNode; 428 static Mutex gCursorBoundsMutex; 429 // These two fields go together: we use the mutex to protect access to 430 // m_buttons, so that we, and webview.cpp can look/modify the m_buttons 431 // field safely from our respective threads 432 static Mutex gButtonMutex; 433 WTF::Vector<Container> m_buttons; 434 // end of shared members 435 436 // internal functions 437 private: 438 CacheBuilder& cacheBuilder(); 439 WebCore::Node* currentFocus(); 440 // Compare the new set of buttons to the old one. All of the new 441 // buttons either replace our old ones or should be added to our list. 442 // Then check the old buttons to see if any are no longer needed. 443 void updateButtonList(WTF::Vector<Container>* buttons); 444 void reset(bool fromConstructor); 445 446 void listBoxRequest(WebCoreReply* reply, const uint16_t** labels, 447 size_t count, const int enabled[], size_t enabledCount, 448 bool multiple, const int selected[], size_t selectedCountOrSelection); 449 450 friend class ListBoxReply; 451 struct JavaGlue; 452 struct JavaGlue* m_javaGlue; 453 WebCore::Frame* m_mainFrame; 454 WebCoreReply* m_popupReply; 455 WebCore::Node* m_lastFocused; 456 WebCore::IntRect m_lastFocusedBounds; 457 int m_lastFocusedSelStart; 458 int m_lastFocusedSelEnd; 459 int m_lastMoveGeneration; 460 static Mutex m_contentMutex; // protects ui/core thread pictureset access 461 PictureSet m_content; // the set of pictures to draw (accessed by UI too) 462 SkRegion m_addInval; // the accumulated inval region (not yet drawn) 463 SkRegion m_rebuildInval; // the accumulated region for rebuilt pictures 464 // Used in passToJS to avoid updating the UI text field until after the 465 // key event has been processed. 466 bool m_blockTextfieldUpdates; 467 bool m_skipContentDraw; 468 // Passed in with key events to know when they were generated. Store it 469 // with the cache so that we can ignore stale text changes. 470 int m_textGeneration; 471 CachedRoot* m_temp; 472 SkPicture* m_tempPict; 473 int m_maxXScroll; 474 int m_maxYScroll; 475 int m_scrollOffsetX; // webview.java's current scroll in X 476 int m_scrollOffsetY; // webview.java's current scroll in Y 477 WebCore::IntPoint m_mousePos; 478 bool m_frameCacheOutOfDate; 479 bool m_progressDone; 480 int m_lastPassed; 481 int m_lastVelocity; 482 CachedHistory m_history; 483 int m_screenWidth; // width of the visible rect in document coordinates 484 int m_screenHeight;// height of the visible rect in document coordinates 485 float m_scale; 486 float m_screenWidthScale; 487 unsigned m_domtree_version; 488 bool m_check_domtree_version; 489 PageGroup* m_groupForVisitedLinks; 490 491 SkTDArray<PluginWidgetAndroid*> m_plugins; 492 WebCore::Timer<WebViewCore> m_pluginInvalTimer; pluginInvalTimerFired(WebCore::Timer<WebViewCore> *)493 void pluginInvalTimerFired(WebCore::Timer<WebViewCore>*) { 494 this->drawPlugins(); 495 } 496 497 void doMaxScroll(CacheBuilder::Direction dir); 498 SkPicture* rebuildPicture(const SkIRect& inval); 499 void rebuildPictureSet(PictureSet* ); 500 void sendNotifyProgressFinished(); 501 bool handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* nodePtr); 502 #if DEBUG_NAV_UI 503 uint32_t m_now; 504 #endif 505 }; 506 507 } // namespace android 508 509 #endif // WEBVIEWCORE_H 510