2 * Copyright 2006, The Android Open Source Project
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
29 #include "android_npapi.h"
30 #include "FileChooser.h"
31 #include "CacheBuilder.h"
32 #include "CachedHistory.h"
33 #include "DeviceMotionAndOrientationManager.h"
34 #include "DOMSelection.h"
35 #include "PictureSet.h"
36 #include "PlatformGraphicsContext.h"
38 #include "SkTDArray.h"
41 #include "WebCoreRefObject.h"
42 #include "WebCoreJni.h"
44 #include <ui/KeycodeLabels.h>
45 #include <ui/PixelFormat.h>
50 class HTMLAnchorElement;
51 class HTMLSelectElement;
55 class PlatformKeyboardEvent;
56 class RenderTextControl;
62 #if USE(ACCELERATED_COMPOSITING)
64 class GraphicsLayerAndroid;
69 class BaseLayerAndroid;
72 struct PluginWidgetAndroid;
79 DIRECTION_BACKWARD = 0,
89 AXIS_PARENT_FIRST_CHILD = 5,
98 class WebCoreReply : public WebCoreRefObject {
100 virtual ~WebCoreReply() {}
102 virtual void replyInt(int value) {
103 SkDEBUGF(("WebCoreReply::replyInt(%d) not handled\n", value));
106 virtual void replyIntArray(const int* array, int count) {
107 SkDEBUGF(("WebCoreReply::replyIntArray() not handled\n"));
109 // add more replyFoo signatures as needed
112 // one instance of WebViewCore per page for calling into Java's WebViewCore
113 class WebViewCore : public WebCoreRefObject {
116 * Initialize the native WebViewCore with a JNI environment, a Java
117 * WebViewCore object and the main frame.
119 WebViewCore(JNIEnv* env, jobject javaView, WebCore::Frame* mainframe);
123 static WebViewCore* getWebViewCore(const WebCore::FrameView* view);
124 static WebViewCore* getWebViewCore(const WebCore::ScrollView* view);
126 // Followings are called from native WebCore to Java
129 * Notification that a form was blurred. Pass a message to hide the
130 * keyboard if it was showing for that Node.
131 * @param Node The Node that blurred.
133 void formDidBlur(const WebCore::Node*);
136 * Scroll to an absolute position.
137 * @param x The x coordinate.
138 * @param y The y coordinate.
139 * @param animate If it is true, animate to the new scroll position
141 * This method calls Java to trigger a gradual scroll event.
143 void scrollTo(int x, int y, bool animate = false);
146 * Scroll to the point x,y relative to the current position.
147 * @param x The relative x position.
148 * @param y The relative y position.
149 * @param animate If it is true, animate to the new scroll position
151 void scrollBy(int x, int y, bool animate);
154 * Record the invalid rectangle
156 void contentInvalidate(const WebCore::IntRect &rect);
157 void contentInvalidateAll();
160 * Satisfy any outstanding invalidates, so that the current state
161 * of the DOM is drawn.
166 * copy the layers to the UI side
170 #if USE(ACCELERATED_COMPOSITING)
171 GraphicsLayerAndroid* graphicsRootLayer() const;
174 /** Invalidate the view/screen, NOT the content/DOM, but expressed in
175 * content/DOM coordinates (i.e. they need to eventually be scaled,
176 * by webview into view.java coordinates
178 void viewInvalidate(const WebCore::IntRect& rect);
181 * Invalidate part of the content that may be offscreen at the moment
183 void offInvalidate(const WebCore::IntRect &rect);
186 * Called by webcore when the progress indicator is done
187 * used to rebuild and display any changes in focus
189 void notifyProgressFinished();
192 * Notify the view that WebCore did its first layout.
194 void didFirstLayout();
197 * Notify the view to update the viewport.
199 void updateViewport();
202 * Notify the view to restore the screen width, which in turn restores
203 * the scale. Also restore the scale for the text wrap.
205 void restoreScale(int scale, int textWrapScale);
208 * Tell the java side to update the focused textfield
209 * @param pointer Pointer to the node for the input field.
210 * @param changeToPassword If true, we are changing the textfield to
211 * a password field, and ignore the String
212 * @param text If changeToPassword is false, this is the new text that
213 * should go into the textfield.
215 void updateTextfield(WebCore::Node* pointer,
216 bool changeToPassword, const WTF::String& text);
219 * Tell the java side to update the current selection in the focused
220 * textfield to the WebTextView. This function finds the currently
221 * focused textinput, and passes its selection to java.
222 * If there is no focus, or it is not a text input, this does nothing.
224 void updateTextSelection();
226 void clearTextEntry();
227 // JavaScript support
228 void jsAlert(const WTF::String& url, const WTF::String& text);
229 bool jsConfirm(const WTF::String& url, const WTF::String& text);
230 bool jsPrompt(const WTF::String& url, const WTF::String& message,
231 const WTF::String& defaultValue, WTF::String& result);
232 bool jsUnload(const WTF::String& url, const WTF::String& message);
236 * Tell the Java side that the origin has exceeded its database quota.
237 * @param url The URL of the page that caused the quota overflow
238 * @param databaseIdentifier the id of the database that caused the
240 * @param currentQuota The current quota for the origin
241 * @param estimatedSize The estimated size of the database
243 void exceededDatabaseQuota(const WTF::String& url,
244 const WTF::String& databaseIdentifier,
245 const unsigned long long currentQuota,
246 const unsigned long long estimatedSize);
249 * Tell the Java side that the appcache has exceeded its max size.
250 * @param spaceNeeded is the amount of disk space that would be needed
251 * in order for the last appcache operation to succeed.
253 void reachedMaxAppCacheSize(const unsigned long long spaceNeeded);
256 * Set up the PageGroup's idea of which links have been visited,
257 * with the browser history.
258 * @param group the object to deliver the links to.
260 void populateVisitedLinks(WebCore::PageGroup*);
263 * Instruct the browser to show a Geolocation permission prompt for the
265 * @param origin The origin of the frame requesting Geolocation
268 void geolocationPermissionsShowPrompt(const WTF::String& origin);
270 * Instruct the browser to hide the Geolocation permission prompt.
272 void geolocationPermissionsHidePrompt();
274 jobject getDeviceMotionService();
275 jobject getDeviceOrientationService();
277 void addMessageToConsole(const String& message, unsigned int lineNumber, const String& sourceID, int msgLevel);
280 * Tell the Java side of the scrollbar mode
282 void setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode verticalMode);
285 // Followings support calls from Java to native WebCore
289 WTF::String retrieveHref(int x, int y);
290 WTF::String retrieveAnchorText(int x, int y);
291 WTF::String requestLabel(WebCore::Frame* , WebCore::Node* );
293 // If the focus is a textfield (<input>), textarea, or contentEditable,
294 // scroll the selection on screen (if necessary).
295 void revealSelection();
296 // Create a single picture to represent the drawn DOM (used by navcache)
297 void recordPicture(SkPicture* picture);
299 // Create a set of pictures to represent the drawn DOM, driven by
300 // the invalidated region and the time required to draw (used to draw)
301 void recordPictureSet(PictureSet* master);
302 void moveFocus(WebCore::Frame* frame, WebCore::Node* node);
303 void moveMouse(WebCore::Frame* frame, int x, int y);
304 void moveMouseIfLatest(int moveGeneration,
305 WebCore::Frame* frame, int x, int y);
307 // set the scroll amount that webview.java is currently showing
308 void setScrollOffset(int moveGeneration, int userScrolled, int dx, int dy);
310 void setGlobalBounds(int x, int y, int h, int v);
312 void setSizeScreenWidthAndScale(int width, int height, int screenWidth,
313 float scale, int realScreenWidth, int screenHeight, int anchorX,
314 int anchorY, bool ignoreHeight);
317 * Handle key events from Java.
318 * @return Whether keyCode was handled by this class.
320 bool key(const WebCore::PlatformKeyboardEvent& event);
323 * Handle (trackball) click event from Java
325 void click(WebCore::Frame* frame, WebCore::Node* node);
330 bool handleTouchEvent(int action, Vector<IntPoint>& points, int metaState);
333 * Handle motionUp event from the UI thread (called touchUp in the
336 void touchUp(int touchGeneration, WebCore::Frame* frame,
337 WebCore::Node* node, int x, int y);
340 * Sets the index of the label from a popup
342 void popupReply(int index);
343 void popupReply(const int* array, int count);
346 * Delete text from start to end in the focused textfield.
347 * If start == end, set the selection, but perform no deletion.
348 * If there is no focus, silently fail.
349 * If start and end are out of order, swap them.
351 void deleteSelection(int start, int end, int textGeneration);
354 * Set the selection of the currently focused textfield to (start, end).
355 * If start and end are out of order, swap them.
357 void setSelection(int start, int end);
360 * Modifies the current selection.
362 * direction - The direction in which to alter the selection.
363 * granularity - The granularity of the selection modification.
365 * returns - The selected HTML as a string. This is not a well formed
366 * HTML, rather the selection annotated with the tags of all
367 * intermediary elements it crosses.
369 String modifySelection(const int direction, const int granularity);
372 * In the currently focused textfield, replace the characters from oldStart to oldEnd
373 * (if oldStart == oldEnd, this will be an insert at that position) with replace,
374 * and set the selection to (start, end).
376 void replaceTextfieldText(int oldStart,
377 int oldEnd, const WTF::String& replace, int start, int end,
379 void passToJs(int generation,
380 const WTF::String& , const WebCore::PlatformKeyboardEvent& );
382 * Scroll the focused textfield to (x, y) in document space
384 void scrollFocusedTextInput(float x, int y);
386 * Set the FocusController's active and focused states, so that
387 * the caret will draw (true) or not.
389 void setFocusControllerActive(bool active);
391 void saveDocumentState(WebCore::Frame* frame);
393 void addVisitedLink(const UChar*, int);
395 // TODO: I don't like this hack but I need to access the java object in
396 // order to send it as a parameter to java
397 AutoJObject getJavaObject();
399 // Return the parent WebView Java object associated with this
401 jobject getWebViewJavaObject();
403 void setBackgroundColor(SkColor c);
404 void updateFrameCache();
405 void updateCacheOnNodeChange();
406 void dumpDomTree(bool);
407 void dumpRenderTree(bool);
410 /* We maintain a list of active plugins. The list is edited by the
411 pluginview itself. The list is used to service invals to the plugin
414 void addPlugin(PluginWidgetAndroid*);
415 void removePlugin(PluginWidgetAndroid*);
416 // returns true if the pluginwidgit is in our active list
417 bool isPlugin(PluginWidgetAndroid*) const;
418 void invalPlugin(PluginWidgetAndroid*);
421 // send the current screen size/zoom to all of the plugins in our list
422 void sendPluginVisibleScreen();
424 // send onLoad event to plugins who are descendents of the given frame
425 void notifyPluginsOnFrameLoad(const Frame*);
427 // send this event to all of the plugins in our list
428 void sendPluginEvent(const ANPEvent&);
430 // lookup the plugin widget struct given an NPP
431 PluginWidgetAndroid* getPluginWidget(NPP npp);
433 // return the cursorNode if it is a plugin
434 Node* cursorNodeIsPlugin();
436 // Notify the Java side whether it needs to pass down the touch events
437 void needTouchEvents(bool);
439 void requestKeyboardWithSelection(const WebCore::Node*, int selStart, int selEnd);
440 // Notify the Java side that webkit is requesting a keyboard
441 void requestKeyboard(bool showKeyboard);
443 // Generates a class loader that contains classes from the plugin's apk
444 jclass getPluginClass(const WTF::String& libName, const char* className);
446 // Creates a full screen surface for a plugin
447 void showFullScreenPlugin(jobject webkitPlugin, NPP npp);
449 // Instructs the UI thread to discard the plugin's full-screen surface
450 void hideFullScreenPlugin();
452 // Adds the plugin's view (aka surface) to the view hierarchy
453 jobject addSurface(jobject view, int x, int y, int width, int height);
455 // Updates a Surface coordinates and dimensions for a plugin
456 void updateSurface(jobject childView, int x, int y, int width, int height);
458 // Destroys a SurfaceView for a plugin
459 void destroySurface(jobject childView);
461 // Returns the context (android.content.Context) of the WebView
462 jobject getContext();
464 bool validNodeAndBounds(Frame* , Node* , const IntRect& );
466 // Make the rect (left, top, width, height) visible. If it can be fully
467 // fit, center it on the screen. Otherwise make sure the point specified
468 // by (left + xPercentInDoc * width, top + yPercentInDoc * height)
469 // pinned at the screen position (xPercentInView, yPercentInView).
470 void showRect(int left, int top, int width, int height, int contentWidth,
471 int contentHeight, float xPercentInDoc, float xPercentInView,
472 float yPercentInDoc, float yPercentInView);
474 // Scale the rect (x, y, width, height) to make it just fit and centered
475 // in the current view.
476 void centerFitRect(int x, int y, int width, int height);
478 // return a list of rects matching the touch point (x, y) with the slop
479 Vector<IntRect> getTouchHighlightRects(int x, int y, int slop);
481 // other public functions
483 // Open a file chooser for selecting a file to upload
484 void openFileChooser(PassRefPtr<WebCore::FileChooser> );
486 // reset the picture set to empty
489 bool focusBoundsChanged();
491 // record the inval area, and the picture size
492 BaseLayerAndroid* recordContent(SkRegion* , SkIPoint* );
494 // This creates a new BaseLayerAndroid by copying the current m_content
495 // and doing a copy of the layers. The layers' content may be updated
496 // as we are calling layersSync().
497 BaseLayerAndroid* createBaseLayer();
499 int textWrapWidth() const { return m_textWrapWidth; }
500 float scale() const { return m_scale; }
501 float textWrapScale() const { return m_screenWidth * m_scale / m_textWrapWidth; }
502 WebCore::Frame* mainFrame() const { return m_mainFrame; }
503 void updateCursorBounds(const CachedRoot* root,
504 const CachedFrame* cachedFrame, const CachedNode* cachedNode);
505 void updateFrameCacheIfLoading();
507 // utility to split slow parts of the picture set
508 void splitContent(PictureSet*);
510 void notifyWebAppCanBeInstalled();
511 void setWebTextViewAutoFillable(int queryId, const string16& previewSummary);
513 DeviceMotionAndOrientationManager* deviceMotionAndOrientationManager() { return &m_deviceMotionAndOrientationManager; }
515 // these members are shared with webview.cpp
516 static Mutex gFrameCacheMutex;
517 CachedRoot* m_frameCacheKit; // nav data being built by webcore
518 SkPicture* m_navPictureKit;
519 int m_moveGeneration; // copy of state in WebViewNative triggered by move
520 int m_touchGeneration; // copy of state in WebViewNative triggered by touch
521 int m_lastGeneration; // last action using up to date cache
522 bool m_updatedFrameCache;
524 bool m_hasCursorBounds;
525 WebCore::IntRect m_cursorBounds;
526 WebCore::IntRect m_cursorHitBounds;
528 IntPoint m_cursorLocation;
530 static Mutex gCursorBoundsMutex;
531 // These two fields go together: we use the mutex to protect access to
532 // m_buttons, so that we, and webview.cpp can look/modify the m_buttons
533 // field safely from our respective threads
534 static Mutex gButtonMutex;
535 WTF::Vector<Container> m_buttons;
536 bool isPaused() const { return m_isPaused; }
537 void setIsPaused(bool isPaused) { m_isPaused = isPaused; }
538 bool drawIsPaused() const;
539 // end of shared members
541 // internal functions
543 CacheBuilder& cacheBuilder();
544 WebCore::Node* currentFocus();
545 // Compare the new set of buttons to the old one. All of the new
546 // buttons either replace our old ones or should be added to our list.
547 // Then check the old buttons to see if any are no longer needed.
548 void updateButtonList(WTF::Vector<Container>* buttons);
549 void reset(bool fromConstructor);
551 void listBoxRequest(WebCoreReply* reply, const uint16_t** labels,
552 size_t count, const int enabled[], size_t enabledCount,
553 bool multiple, const int selected[], size_t selectedCountOrSelection);
555 friend class ListBoxReply;
557 struct JavaGlue* m_javaGlue;
558 WebCore::Frame* m_mainFrame;
559 WebCoreReply* m_popupReply;
560 WebCore::Node* m_lastFocused;
561 WebCore::IntRect m_lastFocusedBounds;
562 bool m_lastClickWasOnTextInput;
563 int m_lastFocusedSelStart;
564 int m_lastFocusedSelEnd;
565 PictureSet m_content; // the set of pictures to draw
566 SkRegion m_addInval; // the accumulated inval region (not yet drawn)
567 SkRegion m_rebuildInval; // the accumulated region for rebuilt pictures
568 // Used in passToJS to avoid updating the UI text field until after the
569 // key event has been processed.
570 bool m_blockTextfieldUpdates;
571 bool m_focusBoundsChanged;
572 bool m_skipContentDraw;
573 // Passed in with key events to know when they were generated. Store it
574 // with the cache so that we can ignore stale text changes.
575 int m_textGeneration;
577 SkPicture* m_tempPict;
580 int m_scrollOffsetX; // webview.java's current scroll in X
581 int m_scrollOffsetY; // webview.java's current scroll in Y
582 WebCore::IntPoint m_mousePos;
583 bool m_frameCacheOutOfDate;
587 CachedHistory m_history;
588 int m_screenWidth; // width of the visible rect in document coordinates
589 int m_screenHeight;// height of the visible rect in document coordinates
592 unsigned m_domtree_version;
593 bool m_check_domtree_version;
594 PageGroup* m_groupForVisitedLinks;
597 SkTDArray<PluginWidgetAndroid*> m_plugins;
598 WebCore::Timer<WebViewCore> m_pluginInvalTimer;
599 void pluginInvalTimerFired(WebCore::Timer<WebViewCore>*) {
603 void doMaxScroll(CacheBuilder::Direction dir);
604 SkPicture* rebuildPicture(const SkIRect& inval);
605 void rebuildPictureSet(PictureSet* );
606 void sendNotifyProgressFinished();
607 bool handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* nodePtr);
608 WebCore::HTMLAnchorElement* retrieveAnchorElement(int x, int y);
609 // below are members responsible for accessibility support
610 String modifySelectionTextNavigationAxis(DOMSelection* selection, int direction, int granularity);
611 String modifySelectionDomNavigationAxis(DOMSelection* selection, int direction, int granularity);
612 Text* traverseNonEmptyNonWhitespaceTextNode(Node* fromNode, Node* toNode ,int direction);
613 bool isVisible(Node* node);
614 bool isHeading(Node* node);
615 bool isEmptyOrOnlyWhitespaceTextNode(Node* node);
616 String formatMarkup(DOMSelection* selection);
617 void tryFocusInlineSelectionElement(DOMSelection* selection);
618 bool focusIfFocusableAndNotTextInput(DOMSelection* selection, Node* node);
619 bool setSelection(DOMSelection* selection, Text* textNode, int direction);
620 bool setSelection(DOMSelection* selection, Node* startNode, Node* endNode, int startOffset, int endOffset);
621 Node* m_currentNodeDomNavigationAxis;
623 #if ENABLE(TOUCH_EVENTS)
624 bool m_forwardingTouchEvents;
631 DeviceMotionAndOrientationManager m_deviceMotionAndOrientationManager;
634 // called from constructor, to add this to a global list
635 static void addInstance(WebViewCore*);
636 // called from destructor, to remove this from a global list
637 static void removeInstance(WebViewCore*);
639 // call only from webkit thread (like add/remove), return true if inst
641 static bool isInstance(WebViewCore*);
643 // if there exists at least on WebViewCore instance then we return the
644 // application context, otherwise NULL is returned.
645 static jobject getApplicationContext();
647 // Check whether a media mimeType is supported in Android media framework.
648 static bool isSupportedMediaMimeType(const WTF::String& mimeType);
651 } // namespace android
653 #endif // WEBVIEWCORE_H