FrameLoaderClientAndroid.cpp revision 8e56126c98940dc57a03335780d4233e8c19b09f
1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/* 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Copyright 2007, The Android Open Source Project 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * Redistribution and use in source and binary forms, with or without 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * modification, are permitted provided that the following conditions 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * are met: 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * * Redistributions of source code must retain the above copyright 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * notice, this list of conditions and the following disclaimer. 9731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick * * Redistributions in binary form must reproduce the above copyright 10731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick * notice, this list of conditions and the following disclaimer in the 11731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick * documentation and/or other materials provided with the distribution. 12731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick * 13731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 14731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 17731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick */ 25731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define LOG_TAG "WebCore" 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "config.h" 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "FrameLoaderClientAndroid.h" 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "BackForwardList.h" 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "CString.h" 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "CachedFrame.h" 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "CachedFramePlatformDataAndroid.h" 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "Chrome.h" 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "ChromeClientAndroid.h" 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "DOMImplementation.h" 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "Document.h" 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "DocumentLoader.h" 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "Frame.h" 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "FrameLoader.h" 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "FrameTree.h" 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "FrameView.h" 44731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "GraphicsContext.h" 45731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "HTMLFrameOwnerElement.h" 46731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "HTMLPlugInElement.h" 47731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "HistoryItem.h" 48731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "IconDatabase.h" 49731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "MIMETypeRegistry.h" 50731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "NotImplemented.h" 51731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "PackageNotifier.h" 52731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "Page.h" 53731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "PlatformBridge.h" 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "PlatformGraphicsContext.h" 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "PlatformString.h" 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "PluginDatabase.h" 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "PluginView.h" 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "PluginWidget.h" 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "ProgressTracker.h" 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "RenderPart.h" 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "RenderView.h" 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "RenderWidget.h" 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "ResourceError.h" 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "ResourceHandle.h" 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "ResourceHandleInternal.h" 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "SelectionController.h" 67#include "Settings.h" 68#include "SkCanvas.h" 69#include "SkRect.h" 70#include "TextEncoding.h" 71#include "WebCoreFrameBridge.h" 72#include "WebCoreResourceLoader.h" 73#include "WebHistory.h" 74#include "WebIconDatabase.h" 75#include "WebFrameView.h" 76#include "WebViewCore.h" 77#include "android_graphics.h" 78 79#include <utils/AssetManager.h> 80 81extern android::AssetManager* globalAssetManager(); 82 83namespace android { 84 85static const int EXTRA_LAYOUT_DELAY = 1000; 86 87FrameLoaderClientAndroid::FrameLoaderClientAndroid(WebFrame* webframe) 88 : m_frame(NULL) 89 , m_webFrame(webframe) 90 , m_manualLoader(NULL) 91 , m_hasSentResponseToPlugin(false) 92 , m_onDemandPluginsEnabled(false) { 93 Retain(m_webFrame); 94} 95 96FrameLoaderClientAndroid* FrameLoaderClientAndroid::get(const WebCore::Frame* frame) 97{ 98 return static_cast<FrameLoaderClientAndroid*> (frame->loader()->client()); 99} 100 101void FrameLoaderClientAndroid::frameLoaderDestroyed() { 102 registerForIconNotification(false); 103 m_frame = 0; 104 Release(m_webFrame); 105 delete this; 106} 107 108bool FrameLoaderClientAndroid::hasWebView() const { 109 // FIXME, 110 // there is one web view per page, or top frame. 111 // as android's view is created from Java side, it is always there. 112 return true; 113} 114 115void FrameLoaderClientAndroid::makeRepresentation(DocumentLoader*) { 116 m_onDemandPluginsEnabled = false; 117 // don't use representation 118 verifiedOk(); 119} 120 121void FrameLoaderClientAndroid::forceLayout() { 122 ASSERT(m_frame); 123 m_frame->view()->forceLayout(); 124 // FIXME, should we adjust view size here? 125 m_frame->view()->adjustViewSize(); 126} 127 128void FrameLoaderClientAndroid::forceLayoutForNonHTML() { 129 notImplemented(); 130} 131 132void FrameLoaderClientAndroid::setCopiesOnScroll() { 133 // this is a hint about whether we need to force redraws, or can 134 // just copy the scrolled content. Since we always force a redraw 135 // anyways, we can ignore this call. 136 verifiedOk(); 137} 138 139void FrameLoaderClientAndroid::detachedFromParent2() { 140 // FIXME, ready to detach frame from view 141} 142 143void FrameLoaderClientAndroid::detachedFromParent3() { 144 // FIXME, ready to release view 145 notImplemented(); 146} 147 148// This function is responsible for associating the "id" with a given 149// subresource load. The following functions that accept an "id" are 150// called for each subresource, so they should not be dispatched to the m_frame. 151void FrameLoaderClientAndroid::assignIdentifierToInitialRequest(unsigned long id, 152 DocumentLoader*, const ResourceRequest&) { 153 lowPriority_notImplemented(); 154} 155 156void FrameLoaderClientAndroid::dispatchWillSendRequest(DocumentLoader*, unsigned long id, 157 ResourceRequest&, const ResourceResponse&) { 158 lowPriority_notImplemented(); 159} 160 161bool FrameLoaderClientAndroid::shouldUseCredentialStorage(DocumentLoader*, unsigned long identifier) 162{ 163 notImplemented(); 164 return false; 165} 166 167void FrameLoaderClientAndroid::dispatchDidReceiveAuthenticationChallenge(DocumentLoader*, 168 unsigned long id, const AuthenticationChallenge&) { 169 lowPriority_notImplemented(); 170} 171 172void FrameLoaderClientAndroid::dispatchDidCancelAuthenticationChallenge(DocumentLoader*, 173 unsigned long id, const AuthenticationChallenge&) { 174 lowPriority_notImplemented(); 175} 176 177void FrameLoaderClientAndroid::dispatchDidReceiveResponse(DocumentLoader*, 178 unsigned long id, const ResourceResponse&) { 179 lowPriority_notImplemented(); 180} 181 182void FrameLoaderClientAndroid::dispatchDidReceiveContentLength(DocumentLoader*, 183 unsigned long id, int lengthReceived) { 184 lowPriority_notImplemented(); 185} 186 187void FrameLoaderClientAndroid::dispatchDidFinishLoading(DocumentLoader*, 188 unsigned long id) { 189 lowPriority_notImplemented(); 190} 191 192void FrameLoaderClientAndroid::dispatchDidFailLoading(DocumentLoader* docLoader, 193 unsigned long id, const ResourceError&) { 194 lowPriority_notImplemented(); 195} 196 197bool FrameLoaderClientAndroid::dispatchDidLoadResourceFromMemoryCache(DocumentLoader*, 198 const ResourceRequest&, const ResourceResponse&, int length) { 199 notImplemented(); 200 return false; 201} 202 203void FrameLoaderClientAndroid::dispatchDidLoadResourceByXMLHttpRequest(unsigned long identifier, const ScriptString&) { 204 return; 205} 206 207void FrameLoaderClientAndroid::dispatchDidHandleOnloadEvents() { 208} 209 210void FrameLoaderClientAndroid::dispatchDidReceiveServerRedirectForProvisionalLoad() { 211 ASSERT(m_frame); 212 // Tell the load it was a redirect. 213 m_webFrame->loadStarted(m_frame); 214} 215 216void FrameLoaderClientAndroid::dispatchDidCancelClientRedirect() { 217 notImplemented(); 218} 219 220void FrameLoaderClientAndroid::dispatchWillPerformClientRedirect(const KURL&, 221 double interval, double fireDate) { 222 notImplemented(); 223} 224 225void FrameLoaderClientAndroid::dispatchDidChangeLocationWithinPage() { 226 notImplemented(); 227} 228 229void FrameLoaderClientAndroid::dispatchDidPushStateWithinPage() 230{ 231 notImplemented(); 232} 233 234void FrameLoaderClientAndroid::dispatchDidReplaceStateWithinPage() 235{ 236 notImplemented(); 237} 238 239void FrameLoaderClientAndroid::dispatchDidPopStateWithinPage() 240{ 241 notImplemented(); 242} 243 244void FrameLoaderClientAndroid::dispatchWillClose() { 245 notImplemented(); 246} 247 248void FrameLoaderClientAndroid::dispatchDidReceiveIcon() { 249 ASSERT(m_frame); 250 if (m_frame->tree() && m_frame->tree()->parent()) 251 return; 252 WebCore::String url(m_frame->loader()->url().string()); 253 // Try to obtain the icon image. 254 WebCore::Image* icon = WebCore::iconDatabase()->iconForPageURL( 255 url, WebCore::IntSize(16, 16)); 256 // If the request fails, try the original request url. 257 if (!icon) { 258 DocumentLoader* docLoader = m_frame->loader()->activeDocumentLoader(); 259 KURL originalURL = docLoader->originalRequest().url(); 260 icon = WebCore::iconDatabase()->iconForPageURL( 261 originalURL, WebCore::IntSize(16, 16)); 262 } 263 // There is a bug in webkit where cancelling an icon load is treated as a 264 // failure. When this is fixed, we can ASSERT again that we have an icon. 265 if (icon) { 266 LOGV("Received icon (%p) for %s", icon, 267 url.utf8().data()); 268 m_webFrame->didReceiveIcon(icon); 269 } else { 270 LOGV("Icon data for %s unavailable, registering for notification...", 271 url.utf8().data()); 272 registerForIconNotification(); 273 } 274} 275 276void FrameLoaderClientAndroid::dispatchDidReceiveTouchIconURL(const String& url, bool precomposed) { 277 ASSERT(m_frame); 278 // Do not report sub frame touch icons 279 if (m_frame->tree() && m_frame->tree()->parent()) 280 return; 281 m_webFrame->didReceiveTouchIconURL(url, precomposed); 282} 283 284void FrameLoaderClientAndroid::dispatchDidStartProvisionalLoad() { 285 notImplemented(); 286} 287 288void FrameLoaderClientAndroid::dispatchDidReceiveTitle(const String& title) { 289 ASSERT(m_frame); 290 // Used to check for FrameLoadTypeStandard but we only want to send the title for 291 // the top frame and not sub-frames. 292 if (!m_frame->tree() || !m_frame->tree()->parent()) { 293 m_webFrame->setTitle(title); 294 } 295} 296 297void FrameLoaderClientAndroid::dispatchDidCommitLoad() { 298 verifiedOk(); 299} 300 301static void loadDataIntoFrame(Frame* frame, KURL baseUrl, const String& url, 302 const String& data) { 303 if (baseUrl.isEmpty()) { 304 baseUrl = blankURL(); 305 } 306 ResourceRequest request(baseUrl); 307 CString cstr = data.utf8(); 308 RefPtr<WebCore::SharedBuffer> buf = WebCore::SharedBuffer::create(cstr.data(), cstr.length()); 309 SubstituteData subData(buf, String("text/html"), String("utf-8"), 310 KURL(KURL(), url)); 311 frame->loader()->load(request, subData, false); 312} 313 314void FrameLoaderClientAndroid::dispatchDidFailProvisionalLoad(const ResourceError& error) { 315 ASSERT(m_frame); 316 // Ignore ErrorInterrupted since it is due to a policy interruption. This 317 // is caused by a decision to download the main resource rather than 318 // display it. 319 if (error.errorCode() == InternalErrorInterrupted 320 || error.errorCode() == InternalErrorCancelled) { 321 // If we decided to download the main resource or if the user cancelled 322 // it, make sure we report that the load is done. 323 didFinishLoad(); 324 return; 325 } 326 327 AssetManager* am = globalAssetManager(); 328 329 // Check to see if the error code was not generated internally 330 WebCore::PlatformBridge::rawResId id = WebCore::PlatformBridge::NoDomain; 331 if ((error.errorCode() == ErrorFile || 332 error.errorCode() == ErrorFileNotFound) && 333 (!error.localizedDescription().isEmpty())) { 334 id = WebCore::PlatformBridge::LoadError; 335 } 336 String filename = m_webFrame->getRawResourceFilename(id); 337 if (filename.isEmpty()) 338 return; 339 340 // Grab the error page from the asset manager 341 Asset* a = am->openNonAsset( 342 filename.utf8().data(), Asset::ACCESS_BUFFER); 343 if (!a) 344 return; 345 346 // Take the failing url and encode html entities so javascript urls are not 347 // executed. 348 CString failingUrl = error.failingURL().utf8(); 349 WTF::Vector<char> url; 350 int len = failingUrl.length(); 351 const char* data = failingUrl.data(); 352 for (int i = 0; i < len; i++) { 353 char c = data[i]; 354 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') 355 || (c >= '0' && c <= '9')) 356 url.append(c); 357 else { 358 char buf[16]; 359 int res = sprintf(buf, "&#%d;", c); 360 buf[res] = 0; 361 url.append(buf, res); 362 } 363 } 364 365 // Replace all occurances of %s with the failing url. 366 String s = UTF8Encoding().decode((const char*)a->getBuffer(false), a->getLength()); 367 s = s.replace("%s", String(url.data(), url.size())); 368 369 // Replace all occurances of %e with the error text 370 s = s.replace("%e", error.localizedDescription()); 371 372 // Create the request and the substitute data and tell the FrameLoader to 373 // load with the replacement data. 374 // use KURL(const char*) as KURL(const String& url) can trigger ASSERT for 375 // invalidate URL string. 376 loadDataIntoFrame(m_frame, KURL(ParsedURLString, data), error.failingURL(), s); 377 378 // Delete the asset. 379 delete a; 380} 381 382void FrameLoaderClientAndroid::dispatchDidFailLoad(const ResourceError&) { 383 // called when page is completed with error 384 didFinishLoad(); 385} 386 387void FrameLoaderClientAndroid::dispatchDidFinishDocumentLoad() { 388 // called when finishedParsing 389 lowPriority_notImplemented(); 390} 391 392void FrameLoaderClientAndroid::dispatchDidFinishLoad() { 393 didFinishLoad(); 394} 395 396void FrameLoaderClientAndroid::dispatchDidFirstLayout() { 397 ASSERT(m_frame); 398 m_frame->document()->setExtraLayoutDelay(EXTRA_LAYOUT_DELAY); 399 // we need to do this here instead of dispatchDidFirstVisuallyNonEmptyLayout 400 // so that about:blank will update the screen. 401 if (!m_frame->tree()->parent()) { 402 // Only need to notify Java side for the top frame 403 WebViewCore::getWebViewCore(m_frame->view())->didFirstLayout(); 404 } 405} 406 407void FrameLoaderClientAndroid::dispatchDidFirstVisuallyNonEmptyLayout() 408{ 409 notImplemented(); 410} 411 412Frame* FrameLoaderClientAndroid::dispatchCreatePage() { 413 ASSERT(m_frame); 414#ifdef ANDROID_MULTIPLE_WINDOWS 415 if (m_frame->settings() && m_frame->settings()->supportMultipleWindows()) 416 // Always a user gesture since window.open maps to 417 // ChromeClientAndroid::createWindow 418 return m_webFrame->createWindow(false, true); 419 else 420#endif 421 // If the client doesn't support multiple windows, just replace the 422 // current frame's contents. 423 return m_frame; 424} 425 426void FrameLoaderClientAndroid::dispatchShow() { 427 ASSERT(m_frame); 428 m_frame->view()->invalidate(); 429} 430 431 432static bool TreatAsAttachment(const String& content_disposition) { 433 // Some broken sites just send 434 // Content-Disposition: ; filename="file" 435 // screen those out here. 436 if (content_disposition.startsWith(";")) 437 return false; 438 439 if (content_disposition.startsWith("inline", false)) 440 return false; 441 442 // Some broken sites just send 443 // Content-Disposition: filename="file" 444 // without a disposition token... screen those out. 445 if (content_disposition.startsWith("filename", false)) 446 return false; 447 448 // Also in use is Content-Disposition: name="file" 449 if (content_disposition.startsWith("name", false)) 450 return false; 451 452 // We have a content-disposition of "attachment" or unknown. 453 // RFC 2183, section 2.8 says that an unknown disposition 454 // value should be treated as "attachment" 455 return true; 456} 457 458void FrameLoaderClientAndroid::dispatchDecidePolicyForMIMEType(FramePolicyFunction func, 459 const String& MIMEType, const ResourceRequest& request) { 460 ASSERT(m_frame); 461 ASSERT(func); 462 if (!func) 463 return; 464 if (request.isNull()) { 465 (m_frame->loader()->policyChecker()->*func)(PolicyIgnore); 466 return; 467 } 468 // Default to Use (display internally). 469 PolicyAction action = PolicyUse; 470 // Check if we should Download instead. 471 const ResourceResponse& response = m_frame->loader()->activeDocumentLoader()->response(); 472 const String& content_disposition = response.httpHeaderField("Content-Disposition"); 473 if (!content_disposition.isEmpty()) { 474 // Server wants to override our normal policy. 475 if (TreatAsAttachment(content_disposition)) { 476 // Check to see if we are a sub frame (main frame has no owner element) 477 if (m_frame->ownerElement() != 0) 478 action = PolicyIgnore; 479 else 480 action = PolicyDownload; 481 } 482 } else { 483 // Ask if it can be handled internally. 484 if (!canShowMIMEType(MIMEType)) { 485 // Check to see if we are a sub frame (main frame has no owner element) 486 if (m_frame->ownerElement() != 0) 487 action = PolicyIgnore; 488 else 489 action = PolicyDownload; 490 } 491 } 492 // A status code of 204 indicates no content change. Ignore the result. 493 WebCore::DocumentLoader* docLoader = m_frame->loader()->activeDocumentLoader(); 494 if (docLoader->response().httpStatusCode() == 204) 495 action = PolicyIgnore; 496 (m_frame->loader()->policyChecker()->*func)(action); 497} 498 499void FrameLoaderClientAndroid::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction func, 500 const NavigationAction& action, const ResourceRequest& request, 501 PassRefPtr<FormState> formState, const String& frameName) { 502 ASSERT(m_frame); 503 ASSERT(func); 504 if (!func) 505 return; 506 507 if (request.isNull()) { 508 (m_frame->loader()->policyChecker()->*func)(PolicyIgnore); 509 return; 510 } 511 512 if (action.type() == NavigationTypeFormSubmitted || action.type() == NavigationTypeFormResubmitted) 513 m_frame->loader()->resetMultipleFormSubmissionProtection(); 514 515 // If we get to this point it means that a link has a target that was not 516 // found by the frame tree. Instead of creating a new frame, return the 517 // current frame in dispatchCreatePage. 518 if (canHandleRequest(request)) 519 (m_frame->loader()->policyChecker()->*func)(PolicyUse); 520 else 521 (m_frame->loader()->policyChecker()->*func)(PolicyIgnore); 522} 523 524void FrameLoaderClientAndroid::cancelPolicyCheck() { 525 lowPriority_notImplemented(); 526} 527 528void FrameLoaderClientAndroid::dispatchUnableToImplementPolicy(const ResourceError&) { 529 notImplemented(); 530} 531 532void FrameLoaderClientAndroid::dispatchDecidePolicyForNavigationAction(FramePolicyFunction func, 533 const NavigationAction& action, const ResourceRequest& request, 534 PassRefPtr<FormState> formState) { 535 ASSERT(m_frame); 536 ASSERT(func); 537 if (!func) 538 return; 539 if (request.isNull()) { 540 (m_frame->loader()->policyChecker()->*func)(PolicyIgnore); 541 return; 542 } 543 544 // Reset multiple form submission protection. If this is a resubmission, we check with the 545 // user and reset the protection if they choose to resubmit the form (see WebCoreFrameBridge.cpp) 546 if (action.type() == NavigationTypeFormSubmitted) 547 m_frame->loader()->resetMultipleFormSubmissionProtection(); 548 549 if (action.type() == NavigationTypeFormResubmitted) { 550 m_webFrame->decidePolicyForFormResubmission(func); 551 return; 552 } else { 553 (m_frame->loader()->policyChecker()->*func)(PolicyUse); 554 } 555} 556 557void FrameLoaderClientAndroid::dispatchWillSubmitForm(FramePolicyFunction func, PassRefPtr<FormState>) { 558 ASSERT(m_frame); 559 ASSERT(func); 560 (m_frame->loader()->policyChecker()->*func)(PolicyUse); 561} 562 563void FrameLoaderClientAndroid::dispatchDidLoadMainResource(DocumentLoader*) { 564 notImplemented(); 565} 566 567void FrameLoaderClientAndroid::revertToProvisionalState(DocumentLoader*) { 568 notImplemented(); 569} 570 571void FrameLoaderClientAndroid::setMainDocumentError(DocumentLoader* docLoader, const ResourceError& error) { 572 ASSERT(m_frame); 573 if (m_manualLoader) { 574 m_manualLoader->didFail(error); 575 m_manualLoader = NULL; 576 m_hasSentResponseToPlugin = false; 577 } else { 578 if (!error.isNull() && error.errorCode() >= InternalErrorLast) 579 m_webFrame->reportError(error.errorCode(), 580 error.localizedDescription(), error.failingURL()); 581 } 582} 583 584// This function is called right before the progress is updated. 585void FrameLoaderClientAndroid::willChangeEstimatedProgress() { 586 verifiedOk(); 587} 588 589// This function is called after the progress has been updated. The bad part 590// about this is that when a page is completed, this function is called after 591// the progress has been reset to 0. 592void FrameLoaderClientAndroid::didChangeEstimatedProgress() { 593 verifiedOk(); 594} 595 596// This will give us the initial estimate when the page first starts to load. 597void FrameLoaderClientAndroid::postProgressStartedNotification() { 598 ASSERT(m_frame); 599 if (m_frame->page()) 600 m_webFrame->setProgress(m_frame->page()->progress()->estimatedProgress()); 601} 602 603// This will give us any updated progress including the final progress. 604void FrameLoaderClientAndroid::postProgressEstimateChangedNotification() { 605 ASSERT(m_frame); 606 if (m_frame->page()) 607 m_webFrame->setProgress(m_frame->page()->progress()->estimatedProgress()); 608} 609 610// This is just a notification that the progress has finished. Don't call 611// setProgress(1) because postProgressEstimateChangedNotification will do so. 612void FrameLoaderClientAndroid::postProgressFinishedNotification() { 613 WebViewCore* core = WebViewCore::getWebViewCore(m_frame->view()); 614 if (!m_frame->tree()->parent()) { 615 // only need to notify Java for the top frame 616 core->notifyProgressFinished(); 617 } 618 // notify plugins that the frame has loaded 619 core->notifyPluginsOnFrameLoad(m_frame); 620} 621 622void FrameLoaderClientAndroid::setMainFrameDocumentReady(bool) { 623 // this is only interesting once we provide an external API for the DOM 624 notImplemented(); 625} 626 627void FrameLoaderClientAndroid::startDownload(const ResourceRequest&) { 628 notImplemented(); 629} 630 631void FrameLoaderClientAndroid::willChangeTitle(DocumentLoader*) { 632 verifiedOk(); 633} 634 635void FrameLoaderClientAndroid::didChangeTitle(DocumentLoader* loader) { 636 verifiedOk(); 637} 638 639void FrameLoaderClientAndroid::finishedLoading(DocumentLoader* docLoader) { 640 // Telling the frame we received some data and passing 0 as the data is our 641 // way to get work done that is normally done when the first bit of data is 642 // received, even for the case of a document with no data (like about:blank) 643 if (!m_manualLoader) { 644 committedLoad(docLoader, 0, 0); 645 return; 646 } 647 648 m_manualLoader->didFinishLoading(); 649 m_manualLoader = NULL; 650 m_hasSentResponseToPlugin = false; 651} 652 653void FrameLoaderClientAndroid::updateGlobalHistory() { 654 ASSERT(m_frame); 655 656 DocumentLoader* docLoader = m_frame->loader()->documentLoader(); 657 ASSERT(docLoader); 658 659 // Code copied from FrameLoader.cpp:createHistoryItem 660 // Only add this URL to the database if it is a valid page 661 if (docLoader->unreachableURL().isEmpty() 662 && docLoader->response().httpStatusCode() < 400) { 663 m_webFrame->updateVisitedHistory(docLoader->urlForHistory(), false); 664 if (!docLoader->serverRedirectSourceForHistory().isNull()) 665 m_webFrame->updateVisitedHistory(KURL(ParsedURLString, docLoader->serverRedirectDestinationForHistory()), false); 666 } 667} 668 669void FrameLoaderClientAndroid::updateGlobalHistoryRedirectLinks() { 670 // Note, do we need to do anything where there is no HistoryItem? If we call 671 // updateGlobalHistory(), we will add bunch of "data:xxx" urls for gmail.com 672 // which is not what we want. Opt to do nothing now. 673} 674 675bool FrameLoaderClientAndroid::shouldGoToHistoryItem(HistoryItem* item) const { 676 // hmmm, seems like we might do a more thoughtful check 677 ASSERT(m_frame); 678 return item != NULL; 679} 680 681void FrameLoaderClientAndroid::didDisplayInsecureContent() 682{ 683 notImplemented(); 684} 685 686void FrameLoaderClientAndroid::didRunInsecureContent(SecurityOrigin*) 687{ 688 notImplemented(); 689} 690 691void FrameLoaderClientAndroid::committedLoad(DocumentLoader* loader, const char* data, int length) { 692 if (!m_manualLoader) { 693 ASSERT(m_frame); 694 String encoding = loader->overrideEncoding(); 695 bool userChosen = !encoding.isNull(); 696 if (encoding.isNull()) 697 encoding = loader->response().textEncodingName(); 698 loader->frameLoader()->setEncoding(encoding, userChosen); 699 Document *doc = m_frame->document(); 700 if (doc) 701 loader->frameLoader()->addData(data, length); 702 } 703 if (m_manualLoader) { 704 if (!m_hasSentResponseToPlugin) { 705 m_manualLoader->didReceiveResponse(loader->response()); 706 // Failure could cause the main document to have an error causing 707 // the manual loader to be reset. 708 if (!m_manualLoader) 709 return; 710 m_hasSentResponseToPlugin = true; 711 } 712 m_manualLoader->didReceiveData(data, length); 713 } 714} 715 716ResourceError FrameLoaderClientAndroid::cancelledError(const ResourceRequest& request) { 717 return ResourceError(String(), InternalErrorCancelled, request.url(), String()); 718} 719 720ResourceError FrameLoaderClientAndroid::cannotShowURLError(const ResourceRequest& request) { 721 return ResourceError(String(), InternalErrorCannotShowUrl, request.url(), String()); 722} 723 724ResourceError FrameLoaderClientAndroid::interruptForPolicyChangeError(const ResourceRequest& request) { 725 return ResourceError(String(), InternalErrorInterrupted, request.url(), String()); 726} 727 728ResourceError FrameLoaderClientAndroid::cannotShowMIMETypeError(const ResourceResponse& request) { 729 return ResourceError(String(), InternalErrorCannotShowMimeType, request.url(), String()); 730} 731 732ResourceError FrameLoaderClientAndroid::fileDoesNotExistError(const ResourceResponse& request) { 733 return ResourceError(String(), InternalErrorFileDoesNotExist, request.url(), String()); 734} 735 736ResourceError FrameLoaderClientAndroid::pluginWillHandleLoadError(const ResourceResponse& request) { 737 return ResourceError(String(), InternalErrorPluginWillHandleLoadError, request.url(), String()); 738} 739 740bool FrameLoaderClientAndroid::shouldFallBack(const ResourceError&) { 741 notImplemented(); 742 return false; 743} 744 745bool FrameLoaderClientAndroid::canHandleRequest(const ResourceRequest& request) const { 746 ASSERT(m_frame); 747 // Don't allow hijacking of intrapage navigation 748 if (WebCore::equalIgnoringFragmentIdentifier(request.url(), m_frame->loader()->url())) 749 return true; 750 751 // Don't allow hijacking of iframe urls that are http or https 752 if (request.url().protocol().startsWith("http", false) && 753 m_frame->tree() && m_frame->tree()->parent()) 754 return true; 755 756 return m_webFrame->canHandleRequest(request); 757} 758 759bool FrameLoaderClientAndroid::canShowMIMEType(const String& mimeType) const { 760 // FIXME: This looks like it has to do with whether or not a type can be 761 // shown "internally" (i.e. inside the browser) regardless of whether 762 // or not the browser is doing the rendering, e.g. a full page plugin. 763 if (MIMETypeRegistry::isSupportedImageResourceMIMEType(mimeType) || 764 MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType) || 765 MIMETypeRegistry::isSupportedJavaScriptMIMEType(mimeType) || 766 (m_frame && m_frame->settings() 767 && m_frame->settings()->arePluginsEnabled() 768 && PluginDatabase::installedPlugins()->isMIMETypeRegistered( 769 mimeType)) || 770 DOMImplementation::isTextMIMEType(mimeType) || 771 DOMImplementation::isXMLMIMEType(mimeType)) 772 return true; 773 return false; 774} 775 776bool FrameLoaderClientAndroid::representationExistsForURLScheme(const String&) const { 777 // don't use representation 778 verifiedOk(); 779 return false; 780} 781 782String FrameLoaderClientAndroid::generatedMIMETypeForURLScheme(const String& URLScheme) const { 783 // FIXME, copy from Apple's port 784 String mimetype("x-apple-web-kit/"); 785 mimetype.append(URLScheme.lower()); 786 return mimetype; 787} 788 789void FrameLoaderClientAndroid::frameLoadCompleted() { 790 // copied from Apple port, without this back with sub-frame will trigger ASSERT 791 ASSERT(m_frame); 792} 793 794void FrameLoaderClientAndroid::saveViewStateToItem(HistoryItem* item) { 795 ASSERT(m_frame); 796 ASSERT(item); 797 // We should have added a bridge when the child item was added to its 798 // parent. 799 AndroidWebHistoryBridge* bridge = item->bridge(); 800 ASSERT(bridge); 801 // store the current scale (only) for the top frame 802 if (!m_frame->tree()->parent()) { 803 WebViewCore* webViewCore = WebViewCore::getWebViewCore(m_frame->view()); 804 bridge->setScale((int)(webViewCore->scale() * 100)); 805 bridge->setScreenWidthScale((int)(webViewCore->screenWidthScale() * 100)); 806 } 807 808 WebCore::notifyHistoryItemChanged(item); 809} 810 811void FrameLoaderClientAndroid::restoreViewState() { 812 WebViewCore* webViewCore = WebViewCore::getWebViewCore(m_frame->view()); 813 HistoryItem* item = m_frame->loader()->history()->currentItem(); 814 AndroidWebHistoryBridge* bridge = item->bridge(); 815 // restore the scale (only) for the top frame 816 if (!m_frame->tree()->parent()) { 817 int scale = bridge->scale(); 818 webViewCore->restoreScale(scale); 819 int screenWidthScale = bridge->screenWidthScale(); 820 if (screenWidthScale != scale) 821 webViewCore->restoreScreenWidthScale(screenWidthScale); 822 } 823} 824 825void FrameLoaderClientAndroid::dispatchDidAddBackForwardItem(HistoryItem* item) const { 826 ASSERT(m_frame); 827 m_webFrame->addHistoryItem(item); 828} 829 830void FrameLoaderClientAndroid::dispatchDidRemoveBackForwardItem(HistoryItem* item) const { 831 ASSERT(m_frame); 832 m_webFrame->removeHistoryItem(0); 833} 834 835void FrameLoaderClientAndroid::dispatchDidChangeBackForwardIndex() const { 836 ASSERT(m_frame); 837 BackForwardList* list = m_frame->page()->backForwardList(); 838 ASSERT(list); 839 m_webFrame->updateHistoryIndex(list->backListCount()); 840} 841 842void FrameLoaderClientAndroid::provisionalLoadStarted() { 843 ASSERT(m_frame); 844 m_webFrame->loadStarted(m_frame); 845} 846 847void FrameLoaderClientAndroid::didFinishLoad() { 848 ASSERT(m_frame); 849 m_frame->document()->setExtraLayoutDelay(0); 850 m_webFrame->didFinishLoad(m_frame); 851} 852 853void FrameLoaderClientAndroid::prepareForDataSourceReplacement() { 854 verifiedOk(); 855} 856 857PassRefPtr<DocumentLoader> FrameLoaderClientAndroid::createDocumentLoader( 858 const ResourceRequest& request, const SubstituteData& data) { 859 RefPtr<DocumentLoader> loader = DocumentLoader::create(request, data); 860 return loader.release(); 861} 862 863void FrameLoaderClientAndroid::setTitle(const String& title, const KURL& url) { 864 // Not needed. dispatchDidReceiveTitle is called immediately after this. 865 // url is used to update the Apple port history items. 866 verifiedOk(); 867} 868 869String FrameLoaderClientAndroid::userAgent(const KURL& u) { 870 return m_webFrame->userAgentForURL(&u); 871} 872 873void FrameLoaderClientAndroid::savePlatformDataToCachedFrame(WebCore::CachedFrame* cachedFrame) { 874 CachedFramePlatformDataAndroid* platformData = new CachedFramePlatformDataAndroid(m_frame->settings()); 875 cachedFrame->setCachedFramePlatformData(platformData); 876} 877 878void FrameLoaderClientAndroid::transitionToCommittedFromCachedFrame(WebCore::CachedFrame* cachedFrame) { 879 CachedFramePlatformDataAndroid* platformData = reinterpret_cast<CachedFramePlatformDataAndroid*>(cachedFrame->cachedFramePlatformData()); 880#ifdef ANDROID_META_SUPPORT 881 platformData->restoreMetadata(m_frame->settings()); 882#endif 883 m_webFrame->transitionToCommitted(m_frame); 884} 885 886void FrameLoaderClientAndroid::transitionToCommittedForNewPage() { 887 ASSERT(m_frame); 888 889#ifdef ANDROID_META_SUPPORT 890 // reset metadata settings for the main frame as they are not preserved cross page 891 if (m_frame == m_frame->page()->mainFrame() && m_frame->settings()) 892 m_frame->settings()->resetMetadataSettings(); 893#endif 894 895 // Save the old WebViewCore before creating a new FrameView. There is one 896 // WebViewCore per page. Each frame, including the main frame and sub frame, 897 // has a 1:1 FrameView and WebFrameView. 898 WebViewCore* webViewCore = WebViewCore::getWebViewCore(m_frame->view()); 899 Retain(webViewCore); 900 901 // Save the old WebFrameView's bounds and apply them to the new WebFrameView 902 WebFrameView* oldWebFrameView = static_cast<WebFrameView*> (m_frame->view()->platformWidget()); 903 IntRect bounds = oldWebFrameView->getBounds(); 904 IntRect windowBounds = oldWebFrameView->getWindowBounds(); 905 WebCore::FrameView* oldFrameView = oldWebFrameView->view(); 906 m_frame->createView(bounds.size(), oldFrameView->baseBackgroundColor(), oldFrameView->isTransparent(), IntSize(), false); 907 908 // Create a new WebFrameView for the new FrameView 909 WebFrameView* newFrameView = new WebFrameView(m_frame->view(), webViewCore); 910 newFrameView->setLocation(bounds.x(), bounds.y()); 911 newFrameView->setSize(bounds.width(), bounds.height()); 912 newFrameView->setWindowBounds(windowBounds.x(), windowBounds.y(), windowBounds.width(), windowBounds.height()); 913 // newFrameView attaches itself to FrameView which Retains the reference, so 914 // call Release for newFrameView 915 Release(newFrameView); 916 // WebFrameView Retains webViewCore, so call Release for webViewCore 917 Release(webViewCore); 918 919 m_webFrame->transitionToCommitted(m_frame); 920} 921 922bool FrameLoaderClientAndroid::canCachePage() const { 923 return true; 924} 925 926void FrameLoaderClientAndroid::download(ResourceHandle* handle, const ResourceRequest&, 927 const ResourceRequest&, const ResourceResponse&) { 928 // Get the C++ side of the load listener and tell it to handle the download 929 handle->getInternal()->m_loader->downloadFile(); 930} 931 932WTF::PassRefPtr<WebCore::Frame> FrameLoaderClientAndroid::createFrame(const KURL& url, const String& name, 933 HTMLFrameOwnerElement* ownerElement, const String& referrer, 934 bool allowsScrolling, int marginWidth, int marginHeight) 935{ 936 Frame* parent = ownerElement->document()->frame(); 937 FrameLoaderClientAndroid* loaderC = new FrameLoaderClientAndroid(m_webFrame); 938 RefPtr<Frame> pFrame = Frame::create(parent->page(), ownerElement, loaderC); 939 Frame* newFrame = pFrame.get(); 940 loaderC->setFrame(newFrame); 941 // Append the subframe to the parent and set the name of the subframe. The name must be set after 942 // appending the child so that the name becomes unique. 943 parent->tree()->appendChild(newFrame); 944 newFrame->tree()->setName(name); 945 // Create a new FrameView and WebFrameView for the child frame to draw into. 946 RefPtr<FrameView> frameView = FrameView::create(newFrame); 947 WebFrameView* webFrameView = new WebFrameView(frameView.get(), 948 WebViewCore::getWebViewCore(parent->view())); 949 // frameView Retains webFrameView, so call Release for webFrameView 950 Release(webFrameView); 951 // Attach the frameView to the newFrame. 952 newFrame->setView(frameView); 953 newFrame->init(); 954 newFrame->selection()->setFocused(true); 955 LOGV("::WebCore:: createSubFrame returning %p", newFrame); 956 957 // The creation of the frame may have run arbitrary JavaScript that removed it from the page already. 958 if (!pFrame->page()) 959 return 0; 960 961 parent->loader()->loadURLIntoChildFrame(url, referrer, pFrame.get()); 962 963 // onLoad may cuase the frame to be removed from the document. Allow the RefPtr to delete the child frame. 964 if (!pFrame->tree()->parent()) 965 return NULL; 966 967 return pFrame.release(); 968} 969 970// YouTube flash url path starts with /v/ 971static const char slash_v_slash[] = { '/', 'v', '/' }; 972 973static bool isValidYouTubeVideo(const String& path) 974{ 975 if (!charactersAreAllASCII(path.characters(), path.length())) 976 return false; 977 unsigned int len = path.length(); 978 if (len <= sizeof(slash_v_slash)) // check for more than just /v/ 979 return false; 980 CString str = path.lower().utf8(); 981 const char* data = str.data(); 982 if (memcmp(data, slash_v_slash, sizeof(slash_v_slash)) != 0) 983 return false; 984 // Start after /v/ 985 for (unsigned int i = sizeof(slash_v_slash); i < len; i++) { 986 char c = data[i]; 987 // Check for alpha-numeric characters only. 988 if (WTF::isASCIIAlphanumeric(c) || c == '_' || c == '-') 989 continue; 990 // The url can have more parameters such as &hl=en after the video id. 991 // Once we start seeing extra parameters we can return true. 992 return c == '&' && i > sizeof(slash_v_slash); 993 } 994 return true; 995} 996 997static bool isYouTubeUrl(const KURL& url, const String& mimeType) 998{ 999 String host = url.host(); 1000 bool youtube = host.endsWith("youtube.com") 1001 || host.endsWith("youtube-nocookie.com"); 1002 return youtube && isValidYouTubeVideo(url.path()) 1003 && equalIgnoringCase(mimeType, "application/x-shockwave-flash"); 1004} 1005 1006static bool isYouTubeInstalled() { 1007 return WebCore::packageNotifier().isPackageInstalled("com.google.android.youtube"); 1008} 1009 1010// Use PluginWidget as it is not used by Android for real plugins. 1011class PluginToggleWidget : public PluginWidget { 1012public: 1013 PluginToggleWidget(Frame* parent, const IntSize& size, 1014 HTMLPlugInElement* elem, const KURL& url, 1015 const WTF::Vector<String>& paramNames, 1016 const WTF::Vector<String>& paramValues, const String& mimeType, 1017 bool loadManually) 1018 : m_parent(parent) 1019 , m_size(size) 1020 , m_element(elem) 1021 , m_url(url) 1022 , m_paramNames(paramNames) 1023 , m_paramValues(paramValues) 1024 , m_mimeType(mimeType) 1025 , m_loadManually(loadManually) 1026 { 1027 resize(size); 1028 } 1029 1030 virtual void paint(GraphicsContext* ctx, const IntRect& rect) 1031 { 1032 // Most of this code is copied from PluginView::paintMissingPluginIcon 1033 // with slight modification. 1034 1035 static RefPtr<Image> image; 1036 if (!image) { 1037 image = Image::loadPlatformResource("togglePlugin"); 1038 } 1039 1040 IntRect imageRect(x(), y(), image->width(), image->height()); 1041 1042 int xOffset = (width() - imageRect.width()) >> 1; 1043 int yOffset = (height() - imageRect.height()) >> 1; 1044 1045 imageRect.move(xOffset, yOffset); 1046 1047 if (!rect.intersects(imageRect)) 1048 return; 1049 1050 // FIXME: We need to clip similarly to paintMissingPluginIcon but it is 1051 // way screwed up right now. It has something to do with how we tell 1052 // webkit the scroll position and it causes the placeholder to get 1053 // clipped very badly. http://b/issue?id=2533303 1054 1055 ctx->save(); 1056 ctx->clip(frameRect()); 1057 1058 ctx->setFillColor(Color::white, DeviceColorSpace); 1059 ctx->fillRect(frameRect()); 1060 if (frameRect().contains(imageRect)) { 1061 // Leave a 2 pixel padding. 1062 const int pixelWidth = 2; 1063 IntRect innerRect = frameRect(); 1064 innerRect.inflate(-pixelWidth); 1065 // Draw a 2 pixel light gray border. 1066 ctx->setStrokeColor(Color::lightGray, DeviceColorSpace); 1067 ctx->strokeRect(innerRect, pixelWidth); 1068 } 1069 1070 // Draw the image in the center 1071 ctx->drawImage(image.get(), DeviceColorSpace, imageRect.location()); 1072 ctx->restore(); 1073 } 1074 1075 virtual void handleEvent(Event* event) 1076 { 1077 if (event->type() != eventNames().clickEvent) 1078 return; 1079 1080 Frame* frame = m_parent->page()->mainFrame(); 1081 while (frame) { 1082 RenderView* view = frame->contentRenderer(); 1083 const HashSet<RenderWidget*> widgets = view->widgets(); 1084 HashSet<RenderWidget*>::const_iterator it = widgets.begin(); 1085 HashSet<RenderWidget*>::const_iterator end = widgets.end(); 1086 for (; it != end; ++it) { 1087 Widget* widget = (*it)->widget(); 1088 // PluginWidget is used only with PluginToggleWidget 1089 if (widget->isPluginWidget()) { 1090 PluginToggleWidget* ptw = 1091 static_cast<PluginToggleWidget*>(widget); 1092 ptw->swapPlugin(*it); 1093 } 1094 } 1095 frame = frame->tree()->traverseNext(); 1096 } 1097 } 1098 1099 void swapPlugin(RenderWidget* renderer) { 1100 typedef FrameLoaderClientAndroid FLCA; 1101 FLCA* client = static_cast<FLCA*>(m_parent->loader()->client()); 1102 client->enableOnDemandPlugins(); 1103 WTF::PassRefPtr<PluginView> prpWidget = 1104 PluginView::create(m_parent.get(), 1105 m_size, 1106 m_element, 1107 m_url, 1108 m_paramNames, 1109 m_paramValues, 1110 m_mimeType, 1111 m_loadManually); 1112 RefPtr<Widget> myProtector(this); 1113 prpWidget->focusPluginElement(); 1114 renderer->setWidget(prpWidget); 1115 } 1116 1117private: 1118 RefPtr<Frame> m_parent; 1119 IntSize m_size; 1120 HTMLPlugInElement* m_element; 1121 KURL m_url; 1122 WTF::Vector<String> m_paramNames; 1123 WTF::Vector<String> m_paramValues; 1124 String m_mimeType; 1125 bool m_loadManually; 1126}; 1127 1128WTF::PassRefPtr<Widget> FrameLoaderClientAndroid::createPlugin( 1129 const IntSize& size, 1130 HTMLPlugInElement* element, 1131 const KURL& url, 1132 const WTF::Vector<String>& names, 1133 const WTF::Vector<String>& values, 1134 const String& mimeType, 1135 bool loadManually) { 1136 WTF::PassRefPtr<PluginView> prpWidget = 0; 1137#ifdef ANDROID_PLUGINS 1138 // This is copied from PluginView.cpp. We need to determine if a plugin 1139 // will be found before doing some of the work in PluginView. 1140 String mimeTypeCopy = mimeType; 1141 PluginPackage* plugin = 1142 PluginDatabase::installedPlugins()->findPlugin(url, mimeTypeCopy); 1143 if (!plugin && PluginDatabase::installedPlugins()->refresh()) { 1144 mimeTypeCopy = mimeType; 1145 plugin = PluginDatabase::installedPlugins()->findPlugin(url, 1146 mimeTypeCopy); 1147 } 1148 Settings* settings = m_frame->settings(); 1149 // Do the placeholder if plugins are on-demand and there is a plugin for the 1150 // given mime type. 1151 if (settings && settings->arePluginsOnDemand() && plugin && 1152 !m_onDemandPluginsEnabled) { 1153 return adoptRef(new PluginToggleWidget(m_frame, size, element, url, 1154 names, values, mimeType, loadManually)); 1155 } 1156 prpWidget = PluginView::create(m_frame, 1157 size, 1158 element, 1159 url, 1160 names, 1161 values, 1162 mimeType, 1163 loadManually); 1164 // Return the plugin if it was loaded successfully. Otherwise, fallback to 1165 // the youtube placeholder if possible. No need to check prpWidget as 1166 // PluginView::create will create a PluginView for missing plugins. 1167 // Note: this check really only checks if the plugin was found and not if 1168 // the plugin was loaded. 1169 if (prpWidget->status() == PluginStatusLoadedSuccessfully) 1170 return prpWidget; 1171#endif 1172 // Create an iframe for youtube urls. 1173 if (isYouTubeUrl(url, mimeType) && isYouTubeInstalled()) { 1174 WTF::RefPtr<Frame> frame = createFrame(blankURL(), String(), element, 1175 String(), false, 0, 0); 1176 if (frame) { 1177 // grab everything after /v/ 1178 String videoId = url.path().substring(sizeof(slash_v_slash)); 1179 // Extract just the video id 1180 unsigned videoIdEnd = 0; 1181 for (; videoIdEnd < videoId.length(); videoIdEnd++) { 1182 if (videoId[videoIdEnd] == '&') { 1183 videoId = videoId.left(videoIdEnd); 1184 break; 1185 } 1186 } 1187 AssetManager* am = globalAssetManager(); 1188 Asset* a = am->open("webkit/youtube.html", 1189 Asset::ACCESS_BUFFER); 1190 if (!a) 1191 return NULL; 1192 String s = String((const char*)a->getBuffer(false), a->getLength()); 1193 s = s.replace("VIDEO_ID", videoId); 1194 delete a; 1195 loadDataIntoFrame(frame.get(), 1196 KURL(ParsedURLString, "file:///android_asset/webkit/"), String(), s); 1197 // Transfer ownership to a local refptr. 1198 WTF::RefPtr<Widget> widget(frame->view()); 1199 return widget.release(); 1200 } 1201 } 1202 return prpWidget; 1203} 1204 1205void FrameLoaderClientAndroid::redirectDataToPlugin(Widget* pluginWidget) { 1206 // Do not redirect data if the Widget is our plugin placeholder. 1207 if (pluginWidget->isPluginView()) { 1208 m_manualLoader = static_cast<PluginView*>(pluginWidget); 1209 } 1210} 1211 1212WTF::PassRefPtr<Widget> FrameLoaderClientAndroid::createJavaAppletWidget(const IntSize&, HTMLAppletElement*, 1213 const KURL& baseURL, const WTF::Vector<String>& paramNames, 1214 const WTF::Vector<String>& paramValues) { 1215 // don't support widget yet 1216 notImplemented(); 1217 return 0; 1218} 1219 1220void FrameLoaderClientAndroid::didTransferChildFrameToNewDocument() 1221{ 1222 ASSERT(m_frame); 1223 // m_webFrame points to the WebFrame for the page that our frame previously 1224 // belonged to. If the frame now belongs to a new page, we need to update 1225 // m_webFrame to point to the WebFrame for the new page. 1226 Page* newPage = m_frame->page(); 1227 if (newPage != m_webFrame->page()) { 1228 ChromeClientAndroid* chromeClient = static_cast<ChromeClientAndroid*>(newPage->chrome()->client()); 1229 Release(m_webFrame); 1230 m_webFrame = chromeClient->webFrame(); 1231 Retain(m_webFrame); 1232 } 1233} 1234 1235// This function is used by the <OBJECT> element to determine the type of 1236// the contents and work out if it can render it. 1237ObjectContentType FrameLoaderClientAndroid::objectContentType(const KURL& url, 1238 const String& mimeType) { 1239 return FrameLoader::defaultObjectContentType(url, mimeType); 1240} 1241 1242// This function allows the application to set the correct CSS media 1243// style. Android could use it to set the media style 'handheld'. Safari 1244// may use it to set the media style to 'print' when the user wants to print 1245// a particular web page. 1246String FrameLoaderClientAndroid::overrideMediaType() const { 1247 lowPriority_notImplemented(); 1248 return String(); 1249} 1250 1251// This function is used to re-attach Javascript<->native code classes. 1252void FrameLoaderClientAndroid::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld* world) 1253{ 1254 if (world != mainThreadNormalWorld()) 1255 return; 1256 1257 ASSERT(m_frame); 1258 LOGV("::WebCore:: windowObjectCleared called on frame %p for %s\n", 1259 m_frame, m_frame->loader()->url().string().ascii().data()); 1260 m_webFrame->windowObjectCleared(m_frame); 1261} 1262 1263void FrameLoaderClientAndroid::documentElementAvailable() { 1264} 1265 1266// functions new to Jun-07 tip of tree merge: 1267ResourceError FrameLoaderClientAndroid::blockedError(ResourceRequest const& request) { 1268 return ResourceError(String(), InternalErrorFileDoesNotExist, String(), String()); 1269} 1270 1271// functions new to Nov-07 tip of tree merge: 1272void FrameLoaderClientAndroid::didPerformFirstNavigation() const { 1273 // This seems to be just a notification that the UI can listen to, to 1274 // know if the user has performed first navigation action. 1275 // It is called from 1276 // void FrameLoader::addBackForwardItemClippedAtTarget(bool doClip) 1277 // "Navigation" here means a transition from one page to another that 1278 // ends up in the back/forward list. 1279} 1280 1281void FrameLoaderClientAndroid::registerForIconNotification(bool listen) { 1282 if (listen) 1283 WebIconDatabase::RegisterForIconNotification(this); 1284 else 1285 WebIconDatabase::UnregisterForIconNotification(this); 1286} 1287 1288// This is the WebIconDatabaseClient method for receiving a notification when we 1289// get the icon for the page. 1290void FrameLoaderClientAndroid::didAddIconForPageUrl(const String& pageUrl) { 1291 // This call must happen before dispatchDidReceiveIcon since that method 1292 // may register for icon notifications again since the icon data may have 1293 // to be read from disk. 1294 registerForIconNotification(false); 1295 KURL u(ParsedURLString, pageUrl); 1296 if (equalIgnoringFragmentIdentifier(u, m_frame->loader()->url())) { 1297 dispatchDidReceiveIcon(); 1298 } 1299} 1300 1301} 1302