• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2007, 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 #define LOG_TAG "WebCore"
27 
28 #include "config.h"
29 
30 #include "ApplicationCacheStorage.h"
31 #include "ChromeClientAndroid.h"
32 #include "DatabaseTracker.h"
33 #include "Document.h"
34 #include "PlatformString.h"
35 #include "FloatRect.h"
36 #include "Frame.h"
37 #include "FrameLoader.h"
38 #include "FrameView.h"
39 #include "Geolocation.h"
40 #include "GraphicsLayerAndroid.h"
41 #include "HTMLMediaElement.h"
42 #include "HTMLNames.h"
43 #include "Icon.h"
44 #include "LayerAndroid.h"
45 #include "Page.h"
46 #include "PopupMenuAndroid.h"
47 #include "RenderLayer.h"
48 #include "RenderLayerCompositor.h"
49 #include "ScriptController.h"
50 #include "SearchPopupMenuAndroid.h"
51 #include "WebCoreFrameBridge.h"
52 #include "WebCoreViewBridge.h"
53 #include "WebViewCore.h"
54 #include "WindowFeatures.h"
55 #include "Settings.h"
56 #include "UserGestureIndicator.h"
57 #include <wtf/text/CString.h>
58 
59 namespace android {
60 
61 #if ENABLE(DATABASE)
62 static unsigned long long tryToReclaimDatabaseQuota(SecurityOrigin* originNeedingQuota);
63 #endif
64 
65 #if USE(ACCELERATED_COMPOSITING)
66 
layersSync()67 WebCore::GraphicsLayer* ChromeClientAndroid::layersSync()
68 {
69     if (m_rootGraphicsLayer && m_needsLayerSync && m_webFrame) {
70         // We may have more than one frame, so let's first update all of them
71         // (webkit may want to update the GraphicsLayer tree, and we do *not* want
72         // to find this out when we are painting, as it means we could be summarily
73         // deallocated while painting...)
74         GraphicsLayerAndroid* rootLayer = static_cast<GraphicsLayerAndroid*>(m_rootGraphicsLayer);
75         Vector<const RenderLayer*> listRootLayers;
76         rootLayer->gatherRootLayers(listRootLayers);
77 
78         for (unsigned int i = 0; i < listRootLayers.size(); i++) {
79             RenderLayer* layer = const_cast<RenderLayer*>(listRootLayers[i]);
80             layer->compositor()->updateCompositingLayers();
81         }
82 
83         Frame* frame = m_webFrame->page()->mainFrame();
84         if (FrameView* frameView = frame->view())
85             frameView->syncCompositingStateIncludingSubframes();
86     }
87     m_needsLayerSync = false;
88     return m_rootGraphicsLayer;
89 }
90 
scheduleCompositingLayerSync()91 void ChromeClientAndroid::scheduleCompositingLayerSync()
92 {
93     if (m_needsLayerSync)
94         return;
95     m_needsLayerSync = true;
96     WebViewCore* webViewCore = WebViewCore::getWebViewCore(m_webFrame->page()->mainFrame()->view());
97     if (webViewCore)
98         webViewCore->contentDraw();
99 }
100 
setNeedsOneShotDrawingSynchronization()101 void ChromeClientAndroid::setNeedsOneShotDrawingSynchronization()
102 {
103     // This should not be needed
104 }
105 
attachRootGraphicsLayer(WebCore::Frame *,WebCore::GraphicsLayer * layer)106 void ChromeClientAndroid::attachRootGraphicsLayer(WebCore::Frame*, WebCore::GraphicsLayer* layer)
107 {
108     // frame is not used in Android as we should only get root graphics layer for the main frame
109     m_rootGraphicsLayer = layer;
110     if (!layer)
111         return;
112     scheduleCompositingLayerSync();
113 }
114 
115 #endif
116 
setWebFrame(android::WebFrame * webframe)117 void ChromeClientAndroid::setWebFrame(android::WebFrame* webframe)
118 {
119     Release(m_webFrame);
120     m_webFrame = webframe;
121     Retain(m_webFrame);
122 }
123 
chromeDestroyed()124 void ChromeClientAndroid::chromeDestroyed()
125 {
126     Release(m_webFrame);
127     delete this;
128 }
129 
setWindowRect(const FloatRect &)130 void ChromeClientAndroid::setWindowRect(const FloatRect&) { notImplemented(); }
131 
windowRect()132 FloatRect ChromeClientAndroid::windowRect() {
133     ASSERT(m_webFrame);
134     if (!m_webFrame)
135         return FloatRect();
136     FrameView* frameView = m_webFrame->page()->mainFrame()->view();
137     if (!frameView)
138         return FloatRect();
139     const WebCoreViewBridge* bridge = frameView->platformWidget();
140     const IntRect& rect = bridge->getWindowBounds();
141     FloatRect fRect(rect.x(), rect.y(), rect.width(), rect.height());
142     return fRect;
143 }
144 
pageRect()145 FloatRect ChromeClientAndroid::pageRect() { notImplemented(); return FloatRect(); }
146 
scaleFactor()147 float ChromeClientAndroid::scaleFactor()
148 {
149     ASSERT(m_webFrame);
150     return m_webFrame->density();
151 }
152 
focus()153 void ChromeClientAndroid::focus()
154 {
155     ASSERT(m_webFrame);
156     bool isUserGesture = UserGestureIndicator::processingUserGesture();
157 
158     // Ask the application to focus this WebView if the action is intiated by the user
159     if (isUserGesture)
160         m_webFrame->requestFocus();
161 }
unfocus()162 void ChromeClientAndroid::unfocus() { notImplemented(); }
163 
canTakeFocus(FocusDirection direction)164 bool ChromeClientAndroid::canTakeFocus(FocusDirection direction)
165 {
166     return android::WebViewCore::getWebViewCore(m_webFrame->page()->mainFrame()->view())->chromeCanTakeFocus(direction);
167 }
168 
takeFocus(FocusDirection direction)169 void ChromeClientAndroid::takeFocus(FocusDirection direction)
170 {
171     android::WebViewCore::getWebViewCore(m_webFrame->page()->mainFrame()->view())->chromeTakeFocus(direction);
172 }
173 
focusedNodeChanged(Node * node)174 void ChromeClientAndroid::focusedNodeChanged(Node* node)
175 {
176     android::WebViewCore::getWebViewCore(m_webFrame->page()->mainFrame()->view())->focusNodeChanged(node);
177 }
178 
focusedFrameChanged(Frame *)179 void ChromeClientAndroid::focusedFrameChanged(Frame*) { notImplemented(); }
180 
createWindow(Frame * frame,const FrameLoadRequest &,const WindowFeatures & features,const NavigationAction &)181 Page* ChromeClientAndroid::createWindow(Frame* frame, const FrameLoadRequest&,
182         const WindowFeatures& features, const NavigationAction&)
183 {
184     ASSERT(frame);
185 #ifdef ANDROID_MULTIPLE_WINDOWS
186     if (frame->settings() && !(frame->settings()->supportMultipleWindows()))
187         // If the client doesn't support multiple windows, just return the current page
188         return frame->page();
189 #endif
190 
191     FloatRect window = windowRect();
192     bool dialog = features.dialog || !features.resizable
193             || (features.heightSet && features.height < window.height()
194                     && features.widthSet && features.width < window.width())
195             || (!features.menuBarVisible && !features.statusBarVisible
196                     && !features.toolBarVisible && !features.locationBarVisible
197                     && !features.scrollbarsVisible);
198     // fullscreen definitely means no dialog
199     if (features.fullscreen)
200         dialog = false;
201     WebCore::Frame* newFrame = m_webFrame->createWindow(dialog,
202             ScriptController::processingUserGesture());
203     if (newFrame) {
204         WebCore::Page* page = newFrame->page();
205         page->setGroupName(frame->page()->groupName());
206         return page;
207     }
208     return NULL;
209 }
210 
show()211 void ChromeClientAndroid::show() { notImplemented(); }
212 
canRunModal()213 bool ChromeClientAndroid::canRunModal() { notImplemented(); return false; }
runModal()214 void ChromeClientAndroid::runModal() { notImplemented(); }
215 
setToolbarsVisible(bool)216 void ChromeClientAndroid::setToolbarsVisible(bool) { notImplemented(); }
toolbarsVisible()217 bool ChromeClientAndroid::toolbarsVisible() { notImplemented(); return false; }
218 
setStatusbarVisible(bool)219 void ChromeClientAndroid::setStatusbarVisible(bool) { notImplemented(); }
statusbarVisible()220 bool ChromeClientAndroid::statusbarVisible() { notImplemented(); return false; }
221 
setScrollbarsVisible(bool)222 void ChromeClientAndroid::setScrollbarsVisible(bool) { notImplemented(); }
scrollbarsVisible()223 bool ChromeClientAndroid::scrollbarsVisible() { notImplemented(); return false; }
224 
setMenubarVisible(bool)225 void ChromeClientAndroid::setMenubarVisible(bool) { notImplemented(); }
menubarVisible()226 bool ChromeClientAndroid::menubarVisible() { notImplemented(); return false; }
227 
setResizable(bool)228 void ChromeClientAndroid::setResizable(bool) { notImplemented(); }
229 
230 #if ENABLE(CONTEXT_MENUS)
showContextMenu()231 void ChromeClientAndroid::showContextMenu() { notImplemented(); }
232 #endif
233 
234 // This function is called by the JavaScript bindings to print usually an error to
235 // a message console. Pass the message to the java side so that the client can
236 // handle it as it sees fit.
addMessageToConsole(MessageSource,MessageType,MessageLevel msgLevel,const String & message,unsigned int lineNumber,const String & sourceID)237 void ChromeClientAndroid::addMessageToConsole(MessageSource, MessageType, MessageLevel msgLevel, const String& message, unsigned int lineNumber, const String& sourceID) {
238     android::WebViewCore::getWebViewCore(m_webFrame->page()->mainFrame()->view())->addMessageToConsole(message, lineNumber, sourceID, msgLevel);
239 }
240 
formDidBlur(const WebCore::Node * node)241 void ChromeClientAndroid::formDidBlur(const WebCore::Node* node) { notImplemented(); }
canRunBeforeUnloadConfirmPanel()242 bool ChromeClientAndroid::canRunBeforeUnloadConfirmPanel() { return true; }
runBeforeUnloadConfirmPanel(const String & message,Frame * frame)243 bool ChromeClientAndroid::runBeforeUnloadConfirmPanel(const String& message, Frame* frame) {
244     String url = frame->document()->documentURI();
245     return android::WebViewCore::getWebViewCore(frame->view())->jsUnload(url, message);
246 }
247 
closeWindowSoon()248 void ChromeClientAndroid::closeWindowSoon()
249 {
250     ASSERT(m_webFrame);
251     Page* page = m_webFrame->page();
252     Frame* mainFrame = page->mainFrame();
253     // This will prevent javascript cross-scripting during unload
254     page->setGroupName(String());
255     // Stop loading but do not send the unload event
256     mainFrame->loader()->stopLoading(UnloadEventPolicyNone);
257     // Cancel all pending loaders
258     mainFrame->loader()->stopAllLoaders();
259     // Remove all event listeners so that no javascript can execute as a result
260     // of mouse/keyboard events.
261     mainFrame->document()->removeAllEventListeners();
262     // Close the window.
263     m_webFrame->closeWindow(android::WebViewCore::getWebViewCore(mainFrame->view()));
264 }
265 
runJavaScriptAlert(Frame * frame,const String & message)266 void ChromeClientAndroid::runJavaScriptAlert(Frame* frame, const String& message)
267 {
268     String url = frame->document()->documentURI();
269 
270     android::WebViewCore::getWebViewCore(frame->view())->jsAlert(url, message);
271 }
272 
runJavaScriptConfirm(Frame * frame,const String & message)273 bool ChromeClientAndroid::runJavaScriptConfirm(Frame* frame, const String& message)
274 {
275     String url = frame->document()->documentURI();
276 
277     return android::WebViewCore::getWebViewCore(frame->view())->jsConfirm(url, message);
278 }
279 
280 /* This function is called for the javascript method Window.prompt(). A dialog should be shown on
281  * the screen with an input put box. First param is the text, the second is the default value for
282  * the input box, third is return param. If the function returns true, the value set in the third parameter
283  * is provided to javascript, else null is returned to the script.
284  */
runJavaScriptPrompt(Frame * frame,const String & message,const String & defaultValue,String & result)285 bool ChromeClientAndroid::runJavaScriptPrompt(Frame* frame, const String& message, const String& defaultValue, String& result)
286 {
287     String url = frame->document()->documentURI();
288     return android::WebViewCore::getWebViewCore(frame->view())->jsPrompt(url, message, defaultValue, result);
289 }
setStatusbarText(const String &)290 void ChromeClientAndroid::setStatusbarText(const String&) { notImplemented(); }
291 
292 // This is called by the JavaScript interpreter when a script has been running for a long
293 // time. A dialog should be shown to the user asking them if they would like to cancel the
294 // Javascript. If true is returned, the script is cancelled.
295 // To make a device more responsive, we default to return true to disallow long running script.
296 // This implies that some of scripts will not be completed.
shouldInterruptJavaScript()297 bool ChromeClientAndroid::shouldInterruptJavaScript() {
298   FrameView* frameView = m_webFrame->page()->mainFrame()->view();
299   return android::WebViewCore::getWebViewCore(frameView)->jsInterrupt();
300 }
301 
keyboardUIMode()302 KeyboardUIMode ChromeClientAndroid::keyboardUIMode()
303 {
304     return KeyboardAccessTabsToLinks;
305 }
306 
windowResizerRect() const307 IntRect ChromeClientAndroid::windowResizerRect() const { return IntRect(0, 0, 0, 0); }
308 
invalidateWindow(const IntRect &,bool)309 void ChromeClientAndroid::invalidateWindow(const IntRect&, bool)
310 {
311     notImplemented();
312 }
313 
invalidateContentsAndWindow(const IntRect & updateRect,bool)314 void ChromeClientAndroid::invalidateContentsAndWindow(const IntRect& updateRect, bool /*immediate*/)
315 {
316     notImplemented();
317 }
318 
invalidateContentsForSlowScroll(const IntRect & updateRect,bool immediate)319 void ChromeClientAndroid::invalidateContentsForSlowScroll(const IntRect& updateRect, bool immediate)
320 {
321     notImplemented();
322 }
323 
324 // new to change 38068 (Nov 6, 2008)
scroll(const IntSize & scrollDelta,const IntRect & rectToScroll,const IntRect & clipRect)325 void ChromeClientAndroid::scroll(const IntSize& scrollDelta,
326         const IntRect& rectToScroll, const IntRect& clipRect) {
327     notImplemented();
328 }
329 
330 // new to change 38068 (Nov 6, 2008)
screenToWindow(const IntPoint &) const331 IntPoint ChromeClientAndroid::screenToWindow(const IntPoint&) const {
332     notImplemented();
333     return IntPoint();
334 }
335 
336 // new to change 38068 (Nov 6, 2008)
windowToScreen(const IntRect &) const337 IntRect ChromeClientAndroid::windowToScreen(const IntRect&) const {
338     notImplemented();
339     return IntRect();
340 }
341 
platformPageClient() const342 PlatformPageClient ChromeClientAndroid::platformPageClient() const {
343     Page* page = m_webFrame->page();
344     Frame* mainFrame = page->mainFrame();
345     FrameView* view = mainFrame->view();
346     PlatformWidget viewBridge = view->platformWidget();
347     return viewBridge;
348 }
349 
contentsSizeChanged(Frame *,const IntSize &) const350 void ChromeClientAndroid::contentsSizeChanged(Frame*, const IntSize&) const
351 {
352     notImplemented();
353 }
354 
scrollRectIntoView(const IntRect &,const ScrollView *) const355 void ChromeClientAndroid::scrollRectIntoView(const IntRect&, const ScrollView*) const
356 {
357     notImplemented();
358 }
359 
formStateDidChange(const Node *)360 void ChromeClientAndroid::formStateDidChange(const Node*)
361 {
362     notImplemented();
363 }
364 
scrollbarsModeDidChange() const365 void ChromeClientAndroid::scrollbarsModeDidChange() const
366 {
367     notImplemented();
368 }
369 
dispatchViewportDataDidChange(const ViewportArguments & input) const370 void ChromeClientAndroid::dispatchViewportDataDidChange(const ViewportArguments& input) const {
371 #ifdef ANDROID_META_SUPPORT
372     const ViewportArguments emptyArgument;
373     if (input == emptyArgument) {
374         // Empty Argument is for a page with no viewport meta tag; so reset everything.
375         m_webFrame->page()->settings()->resetMetadataSettings();
376     }
377     Document* doc = m_webFrame->page()->mainFrame()->document();
378     if (!doc->ownerElement()) {
379         FrameView* view = doc->view();
380         if (view)
381             PlatformBridge::updateViewport(view);
382     }
383 #endif
384 }
385 
mouseDidMoveOverElement(const HitTestResult &,unsigned int)386 void ChromeClientAndroid::mouseDidMoveOverElement(const HitTestResult&, unsigned int) {}
setToolTip(const String &,TextDirection)387 void ChromeClientAndroid::setToolTip(const String&, TextDirection) {}
print(Frame *)388 void ChromeClientAndroid::print(Frame*) {}
389 
390 /*
391  * This function is called on the main (webcore) thread by SQLTransaction::deliverQuotaIncreaseCallback.
392  * The way that the callback mechanism is designed inside SQLTransaction means that there must be a new quota
393  * (which may be equal to the old quota if the user did not allow more quota) when this function returns. As
394  * we call into the browser thread to ask what to do with the quota, we block here and get woken up when the
395  * browser calls the native WebViewCore::SetDatabaseQuota method with the new quota value.
396  */
397 #if ENABLE(DATABASE)
exceededDatabaseQuota(Frame * frame,const String & name)398 void ChromeClientAndroid::exceededDatabaseQuota(Frame* frame, const String& name)
399 {
400     SecurityOrigin* origin = frame->document()->securityOrigin();
401     DatabaseTracker& tracker = WebCore::DatabaseTracker::tracker();
402 
403     m_isNewQuotaSet = false;
404 
405     // This origin is being tracked and has exceeded it's quota. Call into
406     // the Java side of things to inform the user.
407     unsigned long long currentQuota = 0;
408     if (tracker.hasEntryForOrigin(origin))
409         currentQuota = tracker.quotaForOrigin(origin);
410 
411     unsigned long long estimatedSize = 0;
412 
413     // Only update estimatedSize if we are trying to create a a new database, i.e. the usage for the database is 0.
414     if (tracker.usageForDatabase(name, origin) == 0)
415         estimatedSize = tracker.detailsForNameAndOrigin(name, origin).expectedUsage();
416 
417     if (android::WebViewCore::getWebViewCore(frame->view())->exceededDatabaseQuota(frame->document()->documentURI(), name, currentQuota, estimatedSize)) {
418         // We've sent notification to the browser so now wait for it to come back.
419         m_quotaThreadLock.lock();
420         while (!m_isNewQuotaSet) {
421             m_quotaThreadCondition.wait(m_quotaThreadLock);
422         }
423         m_quotaThreadLock.unlock();
424     } else {
425         // We failed to send the message to the UI thread to request a new quota,
426         // so just use the current quota as a default.
427         m_newQuota = currentQuota;
428     }
429 
430     if (m_newQuota < currentQuota)
431         m_newQuota = currentQuota;
432 
433     // If new quota is unavailable, we may be able to resolve the situation by
434     // shrinking the quota of an origin that asked for a lot but is only using a
435     // little. If we find such a site, shrink it's quota and ask Java to try
436     // again.
437     if (m_newQuota == currentQuota && !m_triedToReclaimDBQuota) {
438         m_triedToReclaimDBQuota = true; // we should only try this once per quota overflow.
439         unsigned long long reclaimedQuotaBytes = tryToReclaimDatabaseQuota(origin);
440 
441         // If we were able to free up enough space, try asking Java again.
442         // Otherwise, give up and deny the new database. :(
443         if (reclaimedQuotaBytes >= estimatedSize) {
444             exceededDatabaseQuota(frame, name);
445             return;
446         }
447     }
448 
449     // Update the DatabaseTracker with the new quota value (if the user declined
450     // new quota, this may equal the old quota)
451     tracker.setQuota(origin, m_newQuota);
452     m_triedToReclaimDBQuota = false;
453 }
454 
tryToReclaimDatabaseQuota(SecurityOrigin * originNeedingQuota)455 static unsigned long long tryToReclaimDatabaseQuota(SecurityOrigin* originNeedingQuota) {
456     DatabaseTracker& tracker = WebCore::DatabaseTracker::tracker();
457     Vector<RefPtr<SecurityOrigin> > origins;
458     tracker.origins(origins);
459     unsigned long long reclaimedQuotaBytes = 0;
460     for (unsigned i = 0; i < origins.size(); i++) {
461         SecurityOrigin* originToReclaimFrom = origins[i].get();
462 
463         // Don't try to reclaim from the origin that has exceeded its quota.
464         if (originToReclaimFrom->equal(originNeedingQuota))
465             continue;
466 
467         unsigned long long originUsage = tracker.usageForOrigin(originToReclaimFrom);
468         unsigned long long originQuota = tracker.quotaForOrigin(originToReclaimFrom);
469         // If the origin has a quota that is more than it's current usage +1MB, shrink it.
470         static const int ONE_MB = 1 * 1024 * 1024;
471         if (originUsage + ONE_MB < originQuota) {
472             unsigned long long newQuota = originUsage + ONE_MB;
473             tracker.setQuota(originToReclaimFrom, newQuota);
474             reclaimedQuotaBytes += originQuota - newQuota;
475         }
476     }
477     return reclaimedQuotaBytes;
478 }
479 #endif
480 
481 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
reachedMaxAppCacheSize(int64_t spaceNeeded)482 void ChromeClientAndroid::reachedMaxAppCacheSize(int64_t spaceNeeded)
483 {
484     m_isNewQuotaSet = false;
485     Page* page = m_webFrame->page();
486     Frame* mainFrame = page->mainFrame();
487     FrameView* view = mainFrame->view();
488 
489     // If we fail to send the message to the UI thread to request a new quota,
490     // there's nothing to do.
491     if (!android::WebViewCore::getWebViewCore(view)->reachedMaxAppCacheSize(spaceNeeded))
492         return;
493 
494     // We've sent notification to the browser so now wait for it to come back.
495     m_quotaThreadLock.lock();
496     while (!m_isNewQuotaSet) {
497        m_quotaThreadCondition.wait(m_quotaThreadLock);
498     }
499     m_quotaThreadLock.unlock();
500     if (m_newQuota > 0) {
501         WebCore::cacheStorage().setMaximumSize(m_newQuota);
502         // Now the app cache will retry the saving the previously failed cache.
503     }
504 }
505 #endif
506 
populateVisitedLinks()507 void ChromeClientAndroid::populateVisitedLinks()
508 {
509     Page* page = m_webFrame->page();
510     Frame* mainFrame = page->mainFrame();
511     FrameView* view = mainFrame->view();
512     android::WebViewCore::getWebViewCore(view)->populateVisitedLinks(&page->group());
513 }
514 
runOpenPanel(Frame * frame,PassRefPtr<FileChooser> chooser)515 void ChromeClientAndroid::runOpenPanel(Frame* frame,
516         PassRefPtr<FileChooser> chooser)
517 {
518     android::WebViewCore* core = android::WebViewCore::getWebViewCore(
519             frame->view());
520     core->openFileChooser(chooser);
521 }
522 
chooseIconForFiles(const Vector<WTF::String> &,FileChooser *)523 void ChromeClientAndroid::chooseIconForFiles(const Vector<WTF::String>&, FileChooser*)
524 {
525     notImplemented();
526 }
527 
setCursor(const Cursor &)528 void ChromeClientAndroid::setCursor(const Cursor&)
529 {
530     notImplemented();
531 }
532 
wakeUpMainThreadWithNewQuota(long long newQuota)533 void ChromeClientAndroid::wakeUpMainThreadWithNewQuota(long long newQuota) {
534     MutexLocker locker(m_quotaThreadLock);
535     m_newQuota = newQuota < 0 ? 0 : newQuota;
536     m_isNewQuotaSet = true;
537     m_quotaThreadCondition.signal();
538 }
539 
540 #if ENABLE(TOUCH_EVENTS)
needTouchEvents(bool needTouchEvents)541 void ChromeClientAndroid::needTouchEvents(bool needTouchEvents)
542 {
543     FrameView* frameView = m_webFrame->page()->mainFrame()->view();
544     android::WebViewCore* core = android::WebViewCore::getWebViewCore(frameView);
545     if (core)
546         core->needTouchEvents(needTouchEvents);
547 }
548 #endif
549 
selectItemWritingDirectionIsNatural()550 bool ChromeClientAndroid::selectItemWritingDirectionIsNatural()
551 {
552     return false;
553 }
554 
selectItemAlignmentFollowsMenuWritingDirection()555 bool ChromeClientAndroid::selectItemAlignmentFollowsMenuWritingDirection()
556 {
557     return false;
558 }
559 
createPopupMenu(PopupMenuClient * client) const560 PassRefPtr<PopupMenu> ChromeClientAndroid::createPopupMenu(PopupMenuClient* client) const
561 {
562     return adoptRef(new PopupMenuAndroid(static_cast<ListPopupMenuClient*>(client)));
563 }
564 
createSearchPopupMenu(PopupMenuClient *) const565 PassRefPtr<SearchPopupMenu> ChromeClientAndroid::createSearchPopupMenu(PopupMenuClient*) const
566 {
567     return adoptRef(new SearchPopupMenuAndroid);
568 }
569 
reachedApplicationCacheOriginQuota(SecurityOrigin *)570 void ChromeClientAndroid::reachedApplicationCacheOriginQuota(SecurityOrigin*)
571 {
572     notImplemented();
573 }
574 
575 #if ENABLE(VIDEO)
supportsFullscreenForNode(const Node * node)576 bool ChromeClientAndroid::supportsFullscreenForNode(const Node* node)
577 {
578       return node->hasTagName(HTMLNames::videoTag);
579 }
580 
enterFullscreenForNode(Node * node)581 void ChromeClientAndroid::enterFullscreenForNode(Node* node)
582 {
583       if (!node->hasTagName(HTMLNames::videoTag))
584           return;
585 
586       HTMLMediaElement* videoElement = static_cast<HTMLMediaElement*>(node);
587 
588       FrameView* frameView = m_webFrame->page()->mainFrame()->view();
589       android::WebViewCore* core = android::WebViewCore::getWebViewCore(frameView);
590       if (core)
591           core->enterFullscreenForVideoLayer();
592 
593       MediaPlayer* player = videoElement->player();
594       if (player) {
595           // We need to use the same document object as the
596           // MediaPlayerPrivateAndroid::onStopFullscreen().
597           Document* doc = player->mediaPlayerClient()->mediaPlayerOwningDocument();
598           if (doc)
599               doc->webkitWillEnterFullScreenForElement(videoElement);
600           // Now the player is responsible to trigger to the java side for
601           // entering full screen mode.
602           player->enterFullscreenMode();
603       }
604 }
605 
exitFullscreenForNode(Node * node)606 void ChromeClientAndroid::exitFullscreenForNode(Node* node)
607 {
608     FrameView* frameView = m_webFrame->page()->mainFrame()->view();
609     android::WebViewCore* core = android::WebViewCore::getWebViewCore(frameView);
610     if (core)
611         core->exitFullscreenVideo();
612     return;
613 }
614 #endif
615 
616 #if ENABLE(FULLSCREEN_API)
exitFullScreenForElement(Element * element)617 void ChromeClientAndroid::exitFullScreenForElement(Element* element)
618 {
619     if (!element)
620         return;
621 
622     HTMLMediaElement* videoElement = static_cast<HTMLMediaElement*>(element);
623     videoElement->exitFullscreen();
624 }
625 #endif
626 
627 }
628