• 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 
requestGeolocationPermissionForFrame(Frame * frame,Geolocation * geolocation)515 void ChromeClientAndroid::requestGeolocationPermissionForFrame(Frame* frame, Geolocation* geolocation)
516 {
517     ASSERT(geolocation);
518     if (!m_geolocationPermissions) {
519         m_geolocationPermissions = new GeolocationPermissions(android::WebViewCore::getWebViewCore(frame->view()),
520                                                               m_webFrame->page()->mainFrame());
521     }
522     m_geolocationPermissions->queryPermissionState(frame);
523 }
524 
cancelGeolocationPermissionRequestForFrame(Frame * frame,WebCore::Geolocation *)525 void ChromeClientAndroid::cancelGeolocationPermissionRequestForFrame(Frame* frame, WebCore::Geolocation*)
526 {
527     if (m_geolocationPermissions)
528         m_geolocationPermissions->cancelPermissionStateQuery(frame);
529 }
530 
provideGeolocationPermissions(const String & origin,bool allow,bool remember)531 void ChromeClientAndroid::provideGeolocationPermissions(const String &origin, bool allow, bool remember)
532 {
533     ASSERT(m_geolocationPermissions);
534     m_geolocationPermissions->providePermissionState(origin, allow, remember);
535 }
536 
storeGeolocationPermissions()537 void ChromeClientAndroid::storeGeolocationPermissions()
538 {
539     GeolocationPermissions::maybeStorePermanentPermissions();
540 }
541 
onMainFrameLoadStarted()542 void ChromeClientAndroid::onMainFrameLoadStarted()
543 {
544     if (m_geolocationPermissions.get())
545         m_geolocationPermissions->resetTemporaryPermissionStates();
546 }
547 
runOpenPanel(Frame * frame,PassRefPtr<FileChooser> chooser)548 void ChromeClientAndroid::runOpenPanel(Frame* frame,
549         PassRefPtr<FileChooser> chooser)
550 {
551     android::WebViewCore* core = android::WebViewCore::getWebViewCore(
552             frame->view());
553     core->openFileChooser(chooser);
554 }
555 
chooseIconForFiles(const Vector<WTF::String> &,FileChooser *)556 void ChromeClientAndroid::chooseIconForFiles(const Vector<WTF::String>&, FileChooser*)
557 {
558     notImplemented();
559 }
560 
setCursor(const Cursor &)561 void ChromeClientAndroid::setCursor(const Cursor&)
562 {
563     notImplemented();
564 }
565 
wakeUpMainThreadWithNewQuota(long long newQuota)566 void ChromeClientAndroid::wakeUpMainThreadWithNewQuota(long long newQuota) {
567     MutexLocker locker(m_quotaThreadLock);
568     m_newQuota = newQuota < 0 ? 0 : newQuota;
569     m_isNewQuotaSet = true;
570     m_quotaThreadCondition.signal();
571 }
572 
573 #if ENABLE(TOUCH_EVENTS)
needTouchEvents(bool needTouchEvents)574 void ChromeClientAndroid::needTouchEvents(bool needTouchEvents)
575 {
576     FrameView* frameView = m_webFrame->page()->mainFrame()->view();
577     android::WebViewCore* core = android::WebViewCore::getWebViewCore(frameView);
578     if (core)
579         core->needTouchEvents(needTouchEvents);
580 }
581 #endif
582 
selectItemWritingDirectionIsNatural()583 bool ChromeClientAndroid::selectItemWritingDirectionIsNatural()
584 {
585     return false;
586 }
587 
selectItemAlignmentFollowsMenuWritingDirection()588 bool ChromeClientAndroid::selectItemAlignmentFollowsMenuWritingDirection()
589 {
590     return false;
591 }
592 
createPopupMenu(PopupMenuClient * client) const593 PassRefPtr<PopupMenu> ChromeClientAndroid::createPopupMenu(PopupMenuClient* client) const
594 {
595     return adoptRef(new PopupMenuAndroid(static_cast<ListPopupMenuClient*>(client)));
596 }
597 
createSearchPopupMenu(PopupMenuClient *) const598 PassRefPtr<SearchPopupMenu> ChromeClientAndroid::createSearchPopupMenu(PopupMenuClient*) const
599 {
600     return adoptRef(new SearchPopupMenuAndroid);
601 }
602 
reachedApplicationCacheOriginQuota(SecurityOrigin *)603 void ChromeClientAndroid::reachedApplicationCacheOriginQuota(SecurityOrigin*)
604 {
605     notImplemented();
606 }
607 
608 #if ENABLE(ANDROID_INSTALLABLE_WEB_APPS)
webAppCanBeInstalled()609 void ChromeClientAndroid::webAppCanBeInstalled()
610 {
611     FrameView* frameView = m_webFrame->page()->mainFrame()->view();
612     android::WebViewCore* core = android::WebViewCore::getWebViewCore(frameView);
613     if (core)
614         core->notifyWebAppCanBeInstalled();
615 }
616 #endif
617 
618 #if ENABLE(VIDEO)
supportsFullscreenForNode(const Node * node)619 bool ChromeClientAndroid::supportsFullscreenForNode(const Node* node)
620 {
621       return node->hasTagName(HTMLNames::videoTag);
622 }
623 
enterFullscreenForNode(Node * node)624 void ChromeClientAndroid::enterFullscreenForNode(Node* node)
625 {
626       if (!node->hasTagName(HTMLNames::videoTag))
627           return;
628 
629       HTMLMediaElement* videoElement = static_cast<HTMLMediaElement*>(node);
630       String url = videoElement->currentSrc();
631       LayerAndroid* layer = videoElement->platformLayer();
632       if (!layer)
633           return;
634 
635       FrameView* frameView = m_webFrame->page()->mainFrame()->view();
636       android::WebViewCore* core = android::WebViewCore::getWebViewCore(frameView);
637       m_webFrame->page()->mainFrame()->document()->webkitWillEnterFullScreenForElement(videoElement);
638       if (core)
639           core->enterFullscreenForVideoLayer(layer->uniqueId(), url);
640 }
641 
exitFullscreenForNode(Node * node)642 void ChromeClientAndroid::exitFullscreenForNode(Node* node)
643 {
644     FrameView* frameView = m_webFrame->page()->mainFrame()->view();
645     android::WebViewCore* core = android::WebViewCore::getWebViewCore(frameView);
646     if (core)
647         core->exitFullscreenVideo();
648     return;
649 }
650 #endif
651 
652 #if ENABLE(FULLSCREEN_API)
exitFullScreenForElement(Element * element)653 void ChromeClientAndroid::exitFullScreenForElement(Element* element)
654 {
655     if (!element)
656         return;
657 
658     HTMLMediaElement* videoElement = static_cast<HTMLMediaElement*>(element);
659     videoElement->exitFullscreen();
660 }
661 #endif
662 
663 }
664