Home | History | Annotate | Download | only in jni
      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:
     81         virtual ~WebCoreReply() {}
     82 
     83         virtual void replyInt(int value) {
     84             SkDEBUGF(("WebCoreReply::replyInt(%d) not handled\n", value));
     85         }
     86 
     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* );
    453         int screenWidth() const { return m_screenWidth; }
    454         int screenHeight() const { return m_screenHeight; }
    455         float scale() const { return m_scale; }
    456         float screenWidthScale() const { return m_screenWidthScale; }
    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;
    486         bool isPaused() const { return m_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;
    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 
    583 }   // namespace android
    584 
    585 #endif // WEBVIEWCORE_H
    586