• 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 APPLE COMPUTER, INC. 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 "CString.h"
33 #include "DatabaseTracker.h"
34 #include "Document.h"
35 #include "PlatformString.h"
36 #include "FloatRect.h"
37 #include "Frame.h"
38 #include "FrameLoader.h"
39 #include "FrameView.h"
40 #include "Geolocation.h"
41 #include "Page.h"
42 #include "Screen.h"
43 #include "ScriptController.h"
44 #include "WebCoreFrameBridge.h"
45 #include "WebCoreViewBridge.h"
46 #include "WebViewCore.h"
47 #include "WindowFeatures.h"
48 #include "Settings.h"
49 
50 namespace android {
51 
setWebFrame(android::WebFrame * webframe)52 void ChromeClientAndroid::setWebFrame(android::WebFrame* webframe)
53 {
54     Release(m_webFrame);
55     m_webFrame = webframe;
56     Retain(m_webFrame);
57 }
58 
chromeDestroyed()59 void ChromeClientAndroid::chromeDestroyed()
60 {
61     Release(m_webFrame);
62     delete this;
63 }
64 
setWindowRect(const FloatRect &)65 void ChromeClientAndroid::setWindowRect(const FloatRect&) { notImplemented(); }
66 
windowRect()67 FloatRect ChromeClientAndroid::windowRect() {
68     ASSERT(m_webFrame);
69     if (!m_webFrame)
70         return FloatRect();
71     FrameView* frameView = m_webFrame->page()->mainFrame()->view();
72     if (!frameView)
73         return FloatRect();
74     const WebCoreViewBridge* bridge = frameView->platformWidget();
75     const IntRect& rect = bridge->getWindowBounds();
76     FloatRect fRect(rect.x(), rect.y(), rect.width(), rect.height());
77     return fRect;
78 }
79 
pageRect()80 FloatRect ChromeClientAndroid::pageRect() { notImplemented(); return FloatRect(); }
81 
scaleFactor()82 float ChromeClientAndroid::scaleFactor()
83 {
84     ASSERT(m_webFrame);
85     return m_webFrame->density();
86 }
87 
focus()88 void ChromeClientAndroid::focus() {
89     ASSERT(m_webFrame);
90     // Ask the application to focus this WebView.
91     m_webFrame->requestFocus();
92 }
unfocus()93 void ChromeClientAndroid::unfocus() { notImplemented(); }
94 
canTakeFocus(FocusDirection)95 bool ChromeClientAndroid::canTakeFocus(FocusDirection) { notImplemented(); return false; }
takeFocus(FocusDirection)96 void ChromeClientAndroid::takeFocus(FocusDirection) { notImplemented(); }
97 
createWindow(Frame * frame,const FrameLoadRequest &,const WindowFeatures & features)98 Page* ChromeClientAndroid::createWindow(Frame* frame, const FrameLoadRequest&,
99         const WindowFeatures& features)
100 {
101     ASSERT(frame);
102 #ifdef ANDROID_MULTIPLE_WINDOWS
103     if (frame->settings() && !(frame->settings()->supportMultipleWindows()))
104         // If the client doesn't support multiple windows, just return the current page
105         return frame->page();
106 #endif
107 
108     WTF::PassRefPtr<WebCore::Screen> screen = WebCore::Screen::create(frame);
109     bool dialog = features.dialog || !features.resizable
110             || (features.heightSet && features.height < screen.get()->height()
111                     && features.widthSet && features.width < screen.get()->width())
112             || (!features.menuBarVisible && !features.statusBarVisible
113                     && !features.toolBarVisible && !features.locationBarVisible
114                     && !features.scrollbarsVisible);
115     // fullscreen definitely means no dialog
116     if (features.fullscreen)
117         dialog = false;
118     WebCore::Frame* newFrame = m_webFrame->createWindow(dialog,
119             frame->script()->processingUserGesture());
120     if (newFrame) {
121         WebCore::Page* page = newFrame->page();
122         page->setGroupName(frame->page()->groupName());
123         return page;
124     }
125     return NULL;
126 }
127 
show()128 void ChromeClientAndroid::show() { notImplemented(); }
129 
canRunModal()130 bool ChromeClientAndroid::canRunModal() { notImplemented(); return false; }
runModal()131 void ChromeClientAndroid::runModal() { notImplemented(); }
132 
setToolbarsVisible(bool)133 void ChromeClientAndroid::setToolbarsVisible(bool) { notImplemented(); }
toolbarsVisible()134 bool ChromeClientAndroid::toolbarsVisible() { notImplemented(); return false; }
135 
setStatusbarVisible(bool)136 void ChromeClientAndroid::setStatusbarVisible(bool) { notImplemented(); }
statusbarVisible()137 bool ChromeClientAndroid::statusbarVisible() { notImplemented(); return false; }
138 
setScrollbarsVisible(bool)139 void ChromeClientAndroid::setScrollbarsVisible(bool) { notImplemented(); }
scrollbarsVisible()140 bool ChromeClientAndroid::scrollbarsVisible() { notImplemented(); return false; }
141 
setMenubarVisible(bool)142 void ChromeClientAndroid::setMenubarVisible(bool) { notImplemented(); }
menubarVisible()143 bool ChromeClientAndroid::menubarVisible() { notImplemented(); return false; }
144 
setResizable(bool)145 void ChromeClientAndroid::setResizable(bool) { notImplemented(); }
146 
147 // This function is called by the JavaScript bindings to print usually an error to
148 // a message console. Pass the message to the java side so that the client can
149 // handle it as it sees fit.
addMessageToConsole(MessageSource,MessageType,MessageLevel,const String & message,unsigned int lineNumber,const String & sourceID)150 void ChromeClientAndroid::addMessageToConsole(MessageSource, MessageType, MessageLevel, const String& message, unsigned int lineNumber, const String& sourceID) {
151     android::WebViewCore::getWebViewCore(m_webFrame->page()->mainFrame()->view())->addMessageToConsole(message, lineNumber, sourceID);
152 }
153 
canRunBeforeUnloadConfirmPanel()154 bool ChromeClientAndroid::canRunBeforeUnloadConfirmPanel() { return true; }
runBeforeUnloadConfirmPanel(const String & message,Frame * frame)155 bool ChromeClientAndroid::runBeforeUnloadConfirmPanel(const String& message, Frame* frame) {
156     String url = frame->document()->documentURI();
157     return android::WebViewCore::getWebViewCore(frame->view())->jsUnload(url, message);
158 }
159 
closeWindowSoon()160 void ChromeClientAndroid::closeWindowSoon()
161 {
162     ASSERT(m_webFrame);
163     Page* page = m_webFrame->page();
164     Frame* mainFrame = page->mainFrame();
165     // This will prevent javascript cross-scripting during unload
166     page->setGroupName(String());
167     // Stop loading but do not send the unload event
168     mainFrame->loader()->stopLoading(false);
169     // Cancel all pending loaders
170     mainFrame->loader()->stopAllLoaders();
171     // Remove all event listeners so that no javascript can execute as a result
172     // of mouse/keyboard events.
173     mainFrame->document()->removeAllEventListeners();
174     // Close the window.
175     m_webFrame->closeWindow(android::WebViewCore::getWebViewCore(mainFrame->view()));
176 }
177 
runJavaScriptAlert(Frame * frame,const String & message)178 void ChromeClientAndroid::runJavaScriptAlert(Frame* frame, const String& message)
179 {
180     String url = frame->document()->documentURI();
181 
182     android::WebViewCore::getWebViewCore(frame->view())->jsAlert(url, message);
183 }
184 
runJavaScriptConfirm(Frame * frame,const String & message)185 bool ChromeClientAndroid::runJavaScriptConfirm(Frame* frame, const String& message)
186 {
187     String url = frame->document()->documentURI();
188 
189     return android::WebViewCore::getWebViewCore(frame->view())->jsConfirm(url, message);
190 }
191 
192 /* This function is called for the javascript method Window.prompt(). A dialog should be shown on
193  * the screen with an input put box. First param is the text, the second is the default value for
194  * the input box, third is return param. If the function returns true, the value set in the third parameter
195  * is provided to javascript, else null is returned to the script.
196  */
runJavaScriptPrompt(Frame * frame,const String & message,const String & defaultValue,String & result)197 bool ChromeClientAndroid::runJavaScriptPrompt(Frame* frame, const String& message, const String& defaultValue, String& result)
198 {
199     String url = frame->document()->documentURI();
200     return android::WebViewCore::getWebViewCore(frame->view())->jsPrompt(url, message, defaultValue, result);
201 }
setStatusbarText(const String &)202 void ChromeClientAndroid::setStatusbarText(const String&) { notImplemented(); }
203 
204 // This is called by the JavaScript interpreter when a script has been running for a long
205 // time. A dialog should be shown to the user asking them if they would like to cancel the
206 // Javascript. If true is returned, the script is cancelled.
207 // To make a device more responsive, we default to return true to disallow long running script.
208 // This implies that some of scripts will not be completed.
shouldInterruptJavaScript()209 bool ChromeClientAndroid::shouldInterruptJavaScript() {
210   FrameView* frameView = m_webFrame->page()->mainFrame()->view();
211   return android::WebViewCore::getWebViewCore(frameView)->jsInterrupt();
212 }
213 
tabsToLinks() const214 bool ChromeClientAndroid::tabsToLinks() const { return false; }
215 
windowResizerRect() const216 IntRect ChromeClientAndroid::windowResizerRect() const { return IntRect(0, 0, 0, 0); }
217 
218 // new to change 38068 (Nov 6, 2008)
repaint(const IntRect & rect,bool contentChanged,bool immediate,bool repaintContentOnly)219 void ChromeClientAndroid::repaint(const IntRect& rect, bool contentChanged,
220         bool immediate, bool repaintContentOnly) {
221     notImplemented();
222 // was in ScrollViewAndroid::update() : needs to be something like:
223 //    android::WebViewCore::getWebViewCore(this)->contentInvalidate(rect);
224 }
225 
226 // new to change 38068 (Nov 6, 2008)
scroll(const IntSize & scrollDelta,const IntRect & rectToScroll,const IntRect & clipRect)227 void ChromeClientAndroid::scroll(const IntSize& scrollDelta,
228         const IntRect& rectToScroll, const IntRect& clipRect) {
229     notImplemented();
230 }
231 
232 // new to change 38068 (Nov 6, 2008)
screenToWindow(const IntPoint &) const233 IntPoint ChromeClientAndroid::screenToWindow(const IntPoint&) const {
234     notImplemented();
235     return IntPoint();
236 }
237 
238 // new to change 38068 (Nov 6, 2008)
windowToScreen(const IntRect &) const239 IntRect ChromeClientAndroid::windowToScreen(const IntRect&) const {
240     notImplemented();
241     return IntRect();
242 }
243 
244 // new to change 38068 (Nov 6, 2008)
245 // in place of view()->containingWindow(), webkit now uses view()->hostWindow()->platformWindow()
platformWindow() const246 PlatformWidget ChromeClientAndroid::platformWindow() const {
247     Page* page = m_webFrame->page();
248     Frame* mainFrame = page->mainFrame();
249     FrameView* view = mainFrame->view();
250     PlatformWidget viewBridge = view->platformWidget();
251     return viewBridge;
252 }
253 
contentsSizeChanged(Frame *,const IntSize &) const254 void ChromeClientAndroid::contentsSizeChanged(Frame*, const IntSize&) const
255 {
256     notImplemented();
257 }
258 
scrollRectIntoView(const IntRect &,const ScrollView *) const259 void ChromeClientAndroid::scrollRectIntoView(const IntRect&, const ScrollView*) const
260 {
261     notImplemented();
262 }
263 
formStateDidChange(const Node *)264 void ChromeClientAndroid::formStateDidChange(const Node*)
265 {
266     notImplemented();
267 }
268 
mouseDidMoveOverElement(const HitTestResult &,unsigned int)269 void ChromeClientAndroid::mouseDidMoveOverElement(const HitTestResult&, unsigned int) {}
setToolTip(const String &,TextDirection)270 void ChromeClientAndroid::setToolTip(const String&, TextDirection) {}
print(Frame *)271 void ChromeClientAndroid::print(Frame*) {}
272 
273 /*
274  * This function is called on the main (webcore) thread by SQLTransaction::deliverQuotaIncreaseCallback.
275  * The way that the callback mechanism is designed inside SQLTransaction means that there must be a new quota
276  * (which may be equal to the old quota if the user did not allow more quota) when this function returns. As
277  * we call into the browser thread to ask what to do with the quota, we block here and get woken up when the
278  * browser calls the native WebViewCore::SetDatabaseQuota method with the new quota value.
279  */
280 #if ENABLE(DATABASE)
exceededDatabaseQuota(Frame * frame,const String & name)281 void ChromeClientAndroid::exceededDatabaseQuota(Frame* frame, const String& name)
282 {
283     SecurityOrigin* origin = frame->document()->securityOrigin();
284 
285     // We want to wait on a new quota from the UI thread. Reset the m_newQuota variable to represent we haven't received a new quota.
286     m_newQuota = -1;
287 
288     // This origin is being tracked and has exceeded it's quota. Call into
289     // the Java side of things to inform the user.
290     unsigned long long currentQuota = 0;
291     if (WebCore::DatabaseTracker::tracker().hasEntryForOrigin(origin)) {
292         currentQuota = WebCore::DatabaseTracker::tracker().quotaForOrigin(origin);
293     }
294 
295     unsigned long long estimatedSize = WebCore::DatabaseTracker::tracker().detailsForNameAndOrigin(name, origin).expectedUsage();
296 
297     android::WebViewCore::getWebViewCore(frame->view())->exceededDatabaseQuota(frame->document()->documentURI(), name, currentQuota, estimatedSize);
298 
299     // We've sent notification to the browser so now wait for it to come back.
300     m_quotaThreadLock.lock();
301     while (m_newQuota == -1) {
302         m_quotaThreadCondition.wait(m_quotaThreadLock);
303     }
304     m_quotaThreadLock.unlock();
305 
306     // Update the DatabaseTracker with the new quota value (if the user declined
307     // new quota, this may equal the old quota)
308     DatabaseTracker::tracker().setQuota(origin, m_newQuota);
309 }
310 #endif
311 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
reachedMaxAppCacheSize(int64_t spaceNeeded)312 void ChromeClientAndroid::reachedMaxAppCacheSize(int64_t spaceNeeded)
313 {
314     // Set m_newQuota before calling into the Java side. If we do this after,
315     // we could overwrite the result passed from the Java side and deadlock in the
316     // wait call below.
317     m_newQuota = -1;
318     Page* page = m_webFrame->page();
319     Frame* mainFrame = page->mainFrame();
320     FrameView* view = mainFrame->view();
321     android::WebViewCore::getWebViewCore(view)->reachedMaxAppCacheSize(spaceNeeded);
322 
323     // We've sent notification to the browser so now wait for it to come back.
324     m_quotaThreadLock.lock();
325     while (m_newQuota == -1) {
326        m_quotaThreadCondition.wait(m_quotaThreadLock);
327     }
328     m_quotaThreadLock.unlock();
329     if (m_newQuota > 0) {
330         WebCore::cacheStorage().setMaximumSize(m_newQuota);
331         // Now the app cache will retry the saving the previously failed cache.
332     }
333 }
334 #endif
335 
populateVisitedLinks()336 void ChromeClientAndroid::populateVisitedLinks()
337 {
338     Page* page = m_webFrame->page();
339     Frame* mainFrame = page->mainFrame();
340     FrameView* view = mainFrame->view();
341     android::WebViewCore::getWebViewCore(view)->populateVisitedLinks(&page->group());
342 }
343 
requestGeolocationPermissionForFrame(Frame * frame,Geolocation * geolocation)344 void ChromeClientAndroid::requestGeolocationPermissionForFrame(Frame* frame, Geolocation* geolocation)
345 {
346     ASSERT(geolocation);
347     if (!m_geolocationPermissions) {
348         m_geolocationPermissions = new GeolocationPermissions(android::WebViewCore::getWebViewCore(frame->view()),
349                                                               m_webFrame->page()->mainFrame());
350     }
351     m_geolocationPermissions->queryPermissionState(frame);
352 }
353 
provideGeolocationPermissions(const String & origin,bool allow,bool remember)354 void ChromeClientAndroid::provideGeolocationPermissions(const String &origin, bool allow, bool remember)
355 {
356     ASSERT(m_geolocationPermissions);
357     m_geolocationPermissions->providePermissionState(origin, allow, remember);
358 }
359 
storeGeolocationPermissions()360 void ChromeClientAndroid::storeGeolocationPermissions()
361 {
362     GeolocationPermissions::maybeStorePermanentPermissions();
363 }
364 
onMainFrameLoadStarted()365 void ChromeClientAndroid::onMainFrameLoadStarted()
366 {
367     if (m_geolocationPermissions.get())
368         m_geolocationPermissions->resetTemporaryPermissionStates();
369 }
370 
runOpenPanel(Frame *,PassRefPtr<FileChooser>)371 void ChromeClientAndroid::runOpenPanel(Frame*, PassRefPtr<FileChooser>) { notImplemented(); }
setCursor(PlatformCursorHandle)372 bool ChromeClientAndroid::setCursor(PlatformCursorHandle)
373 {
374     notImplemented();
375     return false;
376 }
377 
wakeUpMainThreadWithNewQuota(long newQuota)378 void ChromeClientAndroid::wakeUpMainThreadWithNewQuota(long newQuota) {
379     MutexLocker locker(m_quotaThreadLock);
380     m_newQuota = newQuota;
381     m_quotaThreadCondition.signal();
382 }
383 
384 }
385