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