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 "PictureSet.h"
34 #include "PlatformGraphicsContext.h"
36 #include "SkTDArray.h"
39 #include "WebCoreRefObject.h"
40 #include "WebCoreJni.h"
42 #include <ui/KeycodeLabels.h>
43 #include <ui/PixelFormat.h>
49 class HTMLAnchorElement;
50 class HTMLSelectElement;
54 class PlatformKeyboardEvent;
55 class RenderTextControl;
61 #if USE(ACCELERATED_COMPOSITING)
63 class GraphicsLayerAndroid;
68 struct PluginWidgetAndroid;
79 class WebCoreReply : public WebCoreRefObject {
81 virtual ~WebCoreReply() {}
83 virtual void replyInt(int value) {
84 SkDEBUGF(("WebCoreReply::replyInt(%d) not handled\n", value));
87 virtual void replyIntArray(const int* array, int count) {
88 SkDEBUGF(("WebCoreReply::replyIntArray() not handled\n"));
90 // add more replyFoo signatures as needed
93 // one instance of WebViewCore per page for calling into Java's WebViewCore
94 class WebViewCore : public WebCoreRefObject {
97 * Initialize the native WebViewCore with a JNI environment, a Java
98 * WebViewCore object and the main frame.
100 WebViewCore(JNIEnv* env, jobject javaView, WebCore::Frame* mainframe);
104 static WebViewCore* getWebViewCore(const WebCore::FrameView* view);
105 static WebViewCore* getWebViewCore(const WebCore::ScrollView* view);
107 // Followings are called from native WebCore to Java
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
115 * This method calls Java to trigger a gradual scroll event.
117 void scrollTo(int x, int y, bool animate = false);
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
125 void scrollBy(int x, int y, bool animate);
128 * Record the invalid rectangle
130 void contentInvalidate(const WebCore::IntRect &rect);
133 * Satisfy any outstanding invalidates, so that the current state
134 * of the DOM is drawn.
138 #if USE(ACCELERATED_COMPOSITING)
139 GraphicsLayerAndroid* graphicsRootLayer() const;
140 void immediateRepaint();
141 void setUIRootLayer(const LayerAndroid* layer);
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
148 void viewInvalidate(const WebCore::IntRect& rect);
151 * Invalidate part of the content that may be offscreen at the moment
153 void offInvalidate(const WebCore::IntRect &rect);
156 * Called by webcore when the progress indicator is done
157 * used to rebuild and display any changes in focus
159 void notifyProgressFinished();
162 * Notify the view that WebCore did its first layout.
164 void didFirstLayout();
167 * Notify the view to update the viewport.
169 void updateViewport();
172 * Notify the view to restore the screen width, which in turn restores
173 * the scale. Also restore the scale for the text wrap.
175 void restoreScale(int scale, int textWrapScale);
178 * Tell the java side to update the focused textfield
179 * @param pointer Pointer to the node for the input field.
180 * @param changeToPassword If true, we are changing the textfield to
181 * a password field, and ignore the String
182 * @param text If changeToPassword is false, this is the new text that
183 * should go into the textfield.
185 void updateTextfield(WebCore::Node* pointer,
186 bool changeToPassword, const WebCore::String& text);
189 * Tell the java side to update the current selection in the focused
190 * textfield to the WebTextView. This function finds the currently
191 * focused textinput, and passes its selection to java.
192 * If there is no focus, or it is not a text input, this does nothing.
194 void updateTextSelection();
196 void clearTextEntry();
197 // JavaScript support
198 void jsAlert(const WebCore::String& url, const WebCore::String& text);
199 bool jsConfirm(const WebCore::String& url, const WebCore::String& text);
200 bool jsPrompt(const WebCore::String& url, const WebCore::String& message,
201 const WebCore::String& defaultValue, WebCore::String& result);
202 bool jsUnload(const WebCore::String& url, const WebCore::String& message);
206 * Tell the Java side that the origin has exceeded its database quota.
207 * @param url The URL of the page that caused the quota overflow
208 * @param databaseIdentifier the id of the database that caused the
210 * @param currentQuota The current quota for the origin
211 * @param estimatedSize The estimated size of the database
213 void exceededDatabaseQuota(const WebCore::String& url,
214 const WebCore::String& databaseIdentifier,
215 const unsigned long long currentQuota,
216 const unsigned long long estimatedSize);
219 * Tell the Java side that the appcache has exceeded its max size.
220 * @param spaceNeeded is the amount of disk space that would be needed
221 * in order for the last appcache operation to succeed.
223 void reachedMaxAppCacheSize(const unsigned long long spaceNeeded);
226 * Set up the PageGroup's idea of which links have been visited,
227 * with the browser history.
228 * @param group the object to deliver the links to.
230 void populateVisitedLinks(WebCore::PageGroup*);
233 * Instruct the browser to show a Geolocation permission prompt for the
235 * @param origin The origin of the frame requesting Geolocation
238 void geolocationPermissionsShowPrompt(const WebCore::String& origin);
240 * Instruct the browser to hide the Geolocation permission prompt.
242 void geolocationPermissionsHidePrompt();
244 void addMessageToConsole(const String& message, unsigned int lineNumber, const String& sourceID, int msgLevel);
247 * Tell the Java side of the scrollbar mode
249 void setScrollbarModes(ScrollbarMode horizontalMode, ScrollbarMode verticalMode);
252 // Followings support calls from Java to native WebCore
256 WebCore::String retrieveHref(WebCore::Frame* frame, WebCore::Node* node);
257 WebCore::String retrieveAnchorText(WebCore::Frame* frame, WebCore::Node* node);
258 WebCore::String requestLabel(WebCore::Frame* , WebCore::Node* );
260 // Create a single picture to represent the drawn DOM (used by navcache)
261 void recordPicture(SkPicture* picture);
263 // Create a set of pictures to represent the drawn DOM, driven by
264 // the invalidated region and the time required to draw (used to draw)
265 void recordPictureSet(PictureSet* master);
266 void moveFocus(WebCore::Frame* frame, WebCore::Node* node);
267 void moveMouse(WebCore::Frame* frame, int x, int y);
268 void moveMouseIfLatest(int moveGeneration,
269 WebCore::Frame* frame, int x, int y);
271 // set the scroll amount that webview.java is currently showing
272 void setScrollOffset(int moveGeneration, int dx, int dy);
274 void setGlobalBounds(int x, int y, int h, int v);
276 void setSizeScreenWidthAndScale(int width, int height, int screenWidth,
277 float scale, int realScreenWidth, int screenHeight, int anchorX,
278 int anchorY, bool ignoreHeight);
281 * Handle key events from Java.
282 * @return Whether keyCode was handled by this class.
284 bool key(const WebCore::PlatformKeyboardEvent& event);
287 * Handle (trackball) click event from Java
289 void click(WebCore::Frame* frame, WebCore::Node* node);
294 bool handleTouchEvent(int action, int x, int y, int metaState);
297 * Handle motionUp event from the UI thread (called touchUp in the
300 void touchUp(int touchGeneration, WebCore::Frame* frame,
301 WebCore::Node* node, int x, int y);
304 * Sets the index of the label from a popup
306 void popupReply(int index);
307 void popupReply(const int* array, int count);
310 * Delete text from start to end in the focused textfield.
311 * If start == end, set the selection, but perform no deletion.
312 * If there is no focus, silently fail.
313 * If start and end are out of order, swap them.
315 void deleteSelection(int start, int end, int textGeneration);
318 * Set the selection of the currently focused textfield to (start, end).
319 * If start and end are out of order, swap them.
321 void setSelection(int start, int end);
324 * Modifies the current selection.
326 * alter - Specifies how to alter the selection.
327 * direction - The direction in which to alter the selection.
328 * granularity - The granularity of the selection modification.
330 * returns - The selection as string.
332 String modifySelection(const String& alter, const String& direction, const String& granularity);
335 * In the currently focused textfield, replace the characters from oldStart to oldEnd
336 * (if oldStart == oldEnd, this will be an insert at that position) with replace,
337 * and set the selection to (start, end).
339 void replaceTextfieldText(int oldStart,
340 int oldEnd, const WebCore::String& replace, int start, int end,
342 void passToJs(int generation,
343 const WebCore::String& , const WebCore::PlatformKeyboardEvent& );
345 * Scroll the focused textfield to (x, y) in document space
347 void scrollFocusedTextInput(float x, int y);
349 * Set the FocusController's active and focused states, so that
350 * the caret will draw (true) or not.
352 void setFocusControllerActive(WebCore::Frame*, bool active);
354 void saveDocumentState(WebCore::Frame* frame);
356 void addVisitedLink(const UChar*, int);
358 // TODO: I don't like this hack but I need to access the java object in
359 // order to send it as a parameter to java
360 AutoJObject getJavaObject();
362 // Return the parent WebView Java object associated with this
364 jobject getWebViewJavaObject();
366 void setBackgroundColor(SkColor c);
367 void updateFrameCache();
368 void updateCacheOnNodeChange();
369 void dumpDomTree(bool);
370 void dumpRenderTree(bool);
373 /* We maintain a list of active plugins. The list is edited by the
374 pluginview itself. The list is used to service invals to the plugin
377 void addPlugin(PluginWidgetAndroid*);
378 void removePlugin(PluginWidgetAndroid*);
379 // returns true if the pluginwidgit is in our active list
380 bool isPlugin(PluginWidgetAndroid*) const;
381 void invalPlugin(PluginWidgetAndroid*);
384 // send the current screen size/zoom to all of the plugins in our list
385 void sendPluginVisibleScreen();
387 // send onLoad event to plugins who are descendents of the given frame
388 void notifyPluginsOnFrameLoad(const Frame*);
390 // send this event to all of the plugins in our list
391 void sendPluginEvent(const ANPEvent&);
393 // lookup the plugin widget struct given an NPP
394 PluginWidgetAndroid* getPluginWidget(NPP npp);
396 // return the cursorNode if it is a plugin
397 Node* cursorNodeIsPlugin();
399 // Notify the Java side whether it needs to pass down the touch events
400 void needTouchEvents(bool);
402 void requestKeyboardWithSelection(const WebCore::Node*, int selStart, int selEnd);
403 // Notify the Java side that webkit is requesting a keyboard
404 void requestKeyboard(bool showKeyboard);
406 // Generates a class loader that contains classes from the plugin's apk
407 jclass getPluginClass(const WebCore::String& libName, const char* className);
409 // Creates a full screen surface for a plugin
410 void showFullScreenPlugin(jobject webkitPlugin, NPP npp);
412 // Instructs the UI thread to discard the plugin's full-screen surface
413 void hideFullScreenPlugin();
415 // Adds the plugin's view (aka surface) to the view hierarchy
416 jobject addSurface(jobject view, int x, int y, int width, int height);
418 // Updates a Surface coordinates and dimensions for a plugin
419 void updateSurface(jobject childView, int x, int y, int width, int height);
421 // Destroys a SurfaceView for a plugin
422 void destroySurface(jobject childView);
424 // Returns the context (android.content.Context) of the WebView
425 jobject getContext();
427 bool validNodeAndBounds(Frame* , Node* , const IntRect& );
429 // Make the rect (left, top, width, height) visible. If it can be fully
430 // fit, center it on the screen. Otherwise make sure the point specified
431 // by (left + xPercentInDoc * width, top + yPercentInDoc * height)
432 // pinned at the screen position (xPercentInView, yPercentInView).
433 void showRect(int left, int top, int width, int height, int contentWidth,
434 int contentHeight, float xPercentInDoc, float xPercentInView,
435 float yPercentInDoc, float yPercentInView);
437 // Scale the rect (x, y, width, height) to make it just fit and centered
438 // in the current view.
439 void centerFitRect(int x, int y, int width, int height);
441 // return a list of rects matching the touch point (x, y) with the slop
442 Vector<IntRect> getTouchHighlightRects(int x, int y, int slop);
444 // other public functions
446 // Open a file chooser for selecting a file to upload
447 void openFileChooser(PassRefPtr<WebCore::FileChooser> );
449 // reset the picture set to empty
452 // flatten the picture set to a picture
453 void copyContentToPicture(SkPicture* );
455 // draw the picture set with the specified background color
456 bool drawContent(SkCanvas* , SkColor );
457 bool focusBoundsChanged();
460 // record the inval area, and the picture size
461 bool recordContent(SkRegion* , SkIPoint* );
462 int textWrapWidth() const { return m_textWrapWidth; }
463 float scale() const { return m_scale; }
464 float textWrapScale() const { return m_screenWidth * m_scale / m_textWrapWidth; }
465 WebCore::Frame* mainFrame() const { return m_mainFrame; }
466 void updateCursorBounds(const CachedRoot* root,
467 const CachedFrame* cachedFrame, const CachedNode* cachedNode);
468 void updateFrameCacheIfLoading();
470 // utility to split slow parts of the picture set
473 void notifyWebAppCanBeInstalled();
475 // these members are shared with webview.cpp
476 static Mutex gFrameCacheMutex;
477 CachedRoot* m_frameCacheKit; // nav data being built by webcore
478 SkPicture* m_navPictureKit;
479 int m_moveGeneration; // copy of state in WebViewNative triggered by move
480 int m_touchGeneration; // copy of state in WebViewNative triggered by touch
481 int m_lastGeneration; // last action using up to date cache
482 bool m_updatedFrameCache;
484 bool m_hasCursorBounds;
485 WebCore::IntRect m_cursorBounds;
486 WebCore::IntRect m_cursorHitBounds;
488 IntPoint m_cursorLocation;
490 static Mutex gCursorBoundsMutex;
491 // These two fields go together: we use the mutex to protect access to
492 // m_buttons, so that we, and webview.cpp can look/modify the m_buttons
493 // field safely from our respective threads
494 static Mutex gButtonMutex;
495 WTF::Vector<Container> m_buttons;
496 bool isPaused() const { return m_isPaused; }
497 void setIsPaused(bool isPaused) { m_isPaused = isPaused; }
498 // end of shared members
500 // internal functions
502 CacheBuilder& cacheBuilder();
503 WebCore::Node* currentFocus();
504 // Compare the new set of buttons to the old one. All of the new
505 // buttons either replace our old ones or should be added to our list.
506 // Then check the old buttons to see if any are no longer needed.
507 void updateButtonList(WTF::Vector<Container>* buttons);
508 void reset(bool fromConstructor);
510 void listBoxRequest(WebCoreReply* reply, const uint16_t** labels,
511 size_t count, const int enabled[], size_t enabledCount,
512 bool multiple, const int selected[], size_t selectedCountOrSelection);
514 friend class ListBoxReply;
516 struct JavaGlue* m_javaGlue;
517 WebCore::Frame* m_mainFrame;
518 WebCoreReply* m_popupReply;
519 WebCore::Node* m_lastFocused;
520 WebCore::IntRect m_lastFocusedBounds;
521 int m_lastFocusedSelStart;
522 int m_lastFocusedSelEnd;
523 static Mutex m_contentMutex; // protects ui/core thread pictureset access
524 PictureSet m_content; // the set of pictures to draw (accessed by UI too)
525 SkRegion m_addInval; // the accumulated inval region (not yet drawn)
526 SkRegion m_rebuildInval; // the accumulated region for rebuilt pictures
527 // Used in passToJS to avoid updating the UI text field until after the
528 // key event has been processed.
529 bool m_blockTextfieldUpdates;
530 bool m_focusBoundsChanged;
531 bool m_skipContentDraw;
532 // Passed in with key events to know when they were generated. Store it
533 // with the cache so that we can ignore stale text changes.
534 int m_textGeneration;
536 SkPicture* m_tempPict;
539 int m_scrollOffsetX; // webview.java's current scroll in X
540 int m_scrollOffsetY; // webview.java's current scroll in Y
541 WebCore::IntPoint m_mousePos;
542 bool m_frameCacheOutOfDate;
546 CachedHistory m_history;
547 int m_screenWidth; // width of the visible rect in document coordinates
548 int m_screenHeight;// height of the visible rect in document coordinates
551 unsigned m_domtree_version;
552 bool m_check_domtree_version;
553 PageGroup* m_groupForVisitedLinks;
556 SkTDArray<PluginWidgetAndroid*> m_plugins;
557 WebCore::Timer<WebViewCore> m_pluginInvalTimer;
558 void pluginInvalTimerFired(WebCore::Timer<WebViewCore>*) {
562 void doMaxScroll(CacheBuilder::Direction dir);
563 SkPicture* rebuildPicture(const SkIRect& inval);
564 void rebuildPictureSet(PictureSet* );
565 void sendNotifyProgressFinished();
566 bool handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* nodePtr);
567 WebCore::HTMLAnchorElement* retrieveAnchorElement(WebCore::Frame* frame, WebCore::Node* node);
569 #if ENABLE(TOUCH_EVENTS)
570 bool m_forwardingTouchEvents;
578 // called from constructor, to add this to a global list
579 static void addInstance(WebViewCore*);
580 // called from destructor, to remove this from a global list
581 static void removeInstance(WebViewCore*);
583 // call only from webkit thread (like add/remove), return true if inst
585 static bool isInstance(WebViewCore*);
587 // if there exists at least on WebViewCore instance then we return the
588 // application context, otherwise NULL is returned.
589 static jobject getApplicationContext();
592 } // namespace android
594 #endif // WEBVIEWCORE_H