1 /* 2 * Copyright (C) 2007, 2008 Alp Toker <alp (at) atoker.com> 3 * Copyright (C) 2007, 2008, 2009 Holger Hans Peter Freyther 4 * Copyright (C) 2007 Christian Dywan <christian (at) twotoasts.de> 5 * Copyright (C) 2008, 2009 Collabora Ltd. All rights reserved. 6 * Copyright (C) 2009, 2010 Gustavo Noronha Silva <gns (at) gnome.org> 7 * Copyright (C) Research In Motion Limited 2009. All rights reserved. 8 * 9 * This library is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU Lesser General Public 11 * License as published by the Free Software Foundation; either 12 * version 2 of the License, or (at your option) any later version. 13 * 14 * This library is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * Lesser General Public License for more details. 18 * 19 * You should have received a copy of the GNU Lesser General Public 20 * License along with this library; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 22 */ 23 24 #include "config.h" 25 #include "FrameLoaderClientGtk.h" 26 27 #include "ArchiveResource.h" 28 #include "CachedFrame.h" 29 #include "Color.h" 30 #include "DocumentLoader.h" 31 #include "DocumentLoaderGtk.h" 32 #include "FormState.h" 33 #include "FrameLoader.h" 34 #include "FrameView.h" 35 #include "FrameTree.h" 36 #include "GOwnPtr.h" 37 #include "GRefPtr.h" 38 #include "GtkPluginWidget.h" 39 #include "HTMLAppletElement.h" 40 #include "HTMLFormElement.h" 41 #include "HTMLFrameElement.h" 42 #include "HTMLFrameOwnerElement.h" 43 #include "HTMLNames.h" 44 #include "HTMLPlugInElement.h" 45 #include "JSDOMWindow.h" 46 #include "Language.h" 47 #include "MIMETypeRegistry.h" 48 #include "MouseEvent.h" 49 #include "NotImplemented.h" 50 #include "PlatformString.h" 51 #include "PluginDatabase.h" 52 #include "RenderPart.h" 53 #include "ResourceHandle.h" 54 #include "ResourceRequest.h" 55 #include "CString.h" 56 #include "ProgressTracker.h" 57 #include "JSDOMBinding.h" 58 #include "ScriptController.h" 59 #include "webkiterror.h" 60 #include "webkitnetworkrequest.h" 61 #include "webkitnetworkresponse.h" 62 #include "webkitprivate.h" 63 #include "webkitwebframe.h" 64 #include "webkitwebnavigationaction.h" 65 #include "webkitwebpolicydecision.h" 66 #include "webkitwebview.h" 67 68 #include <JavaScriptCore/APICast.h> 69 #include <gio/gio.h> 70 #include <glib.h> 71 #include <glib/gi18n-lib.h> 72 #include <stdio.h> 73 74 using namespace WebCore; 75 76 namespace WebKit { 77 78 FrameLoaderClient::FrameLoaderClient(WebKitWebFrame* frame) 79 : m_frame(frame) 80 , m_policyDecision(0) 81 , m_loadingErrorPage(false) 82 , m_pluginView(0) 83 , m_hasSentResponseToPlugin(false) 84 { 85 ASSERT(m_frame); 86 } 87 88 FrameLoaderClient::~FrameLoaderClient() 89 { 90 if (m_policyDecision) 91 g_object_unref(m_policyDecision); 92 } 93 94 String FrameLoaderClient::userAgent(const KURL&) 95 { 96 WebKitWebSettings* settings = webkit_web_view_get_settings(getViewFromFrame(m_frame)); 97 return String::fromUTF8(webkit_web_settings_get_user_agent(settings)); 98 } 99 100 static void notifyStatus(WebKitWebFrame* frame, WebKitLoadStatus loadStatus) 101 { 102 frame->priv->loadStatus = loadStatus; 103 g_object_notify(G_OBJECT(frame), "load-status"); 104 105 WebKitWebView* webView = getViewFromFrame(frame); 106 if (frame == webkit_web_view_get_main_frame(webView)) { 107 webView->priv->loadStatus = loadStatus; 108 g_object_notify(G_OBJECT(webView), "load-status"); 109 } 110 } 111 112 static void loadDone(WebKitWebFrame* frame, bool didSucceed) 113 { 114 // FIXME: load-done is deprecated. Please remove when signal's been removed. 115 g_signal_emit_by_name(frame, "load-done", didSucceed); 116 notifyStatus(frame, WEBKIT_LOAD_FINISHED); 117 } 118 119 WTF::PassRefPtr<WebCore::DocumentLoader> FrameLoaderClient::createDocumentLoader(const WebCore::ResourceRequest& request, const SubstituteData& substituteData) 120 { 121 RefPtr<WebKit::DocumentLoader> loader = WebKit::DocumentLoader::create(request, substituteData); 122 123 WebKitWebDataSource* webDataSource = webkit_web_data_source_new_with_loader(loader.get()); 124 loader->setDataSource(webDataSource); 125 g_object_unref(webDataSource); 126 127 return loader.release(); 128 } 129 130 void FrameLoaderClient::dispatchWillSubmitForm(FramePolicyFunction policyFunction, PassRefPtr<FormState>) 131 { 132 // FIXME: This is surely too simple 133 ASSERT(policyFunction); 134 if (!policyFunction) 135 return; 136 (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyUse); 137 } 138 139 140 void FrameLoaderClient::committedLoad(WebCore::DocumentLoader* loader, const char* data, int length) 141 { 142 if (!m_pluginView) { 143 ASSERT(loader->frame()); 144 // Setting the encoding on the frame loader is our way to get work done that is normally done 145 // when the first bit of data is received, even for the case of a document with no data (like about:blank). 146 String encoding = loader->overrideEncoding(); 147 bool userChosen = !encoding.isNull(); 148 if (!userChosen) 149 encoding = loader->response().textEncodingName(); 150 151 FrameLoader* frameLoader = loader->frameLoader(); 152 frameLoader->setEncoding(encoding, userChosen); 153 if (data) 154 frameLoader->addData(data, length); 155 156 Frame* coreFrame = loader->frame(); 157 if (coreFrame && coreFrame->document() && coreFrame->document()->isMediaDocument()) 158 loader->cancelMainResourceLoad(frameLoader->client()->pluginWillHandleLoadError(loader->response())); 159 } 160 161 if (m_pluginView) { 162 if (!m_hasSentResponseToPlugin) { 163 m_pluginView->didReceiveResponse(loader->response()); 164 m_hasSentResponseToPlugin = true; 165 } 166 167 // FIXME: We may want to investigate refactoring our plugin loading 168 // code to be similar to mac's. 169 // Also, see http://trac.webkit.org/changeset/24118. 170 if (!m_pluginView) 171 return; 172 173 m_pluginView->didReceiveData(data, length); 174 } 175 } 176 177 bool 178 FrameLoaderClient::shouldUseCredentialStorage(WebCore::DocumentLoader*, unsigned long identifier) 179 { 180 notImplemented(); 181 return false; 182 } 183 184 void FrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(WebCore::DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&) 185 { 186 notImplemented(); 187 } 188 189 void FrameLoaderClient::dispatchDidCancelAuthenticationChallenge(WebCore::DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&) 190 { 191 notImplemented(); 192 } 193 194 // We convert this to string because it's easier to use strings as 195 // keys in a GHashTable. 196 static char* toString(unsigned long identifier) 197 { 198 return g_strdup_printf("%ld", identifier); 199 } 200 201 void FrameLoaderClient::dispatchWillSendRequest(WebCore::DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse) 202 { 203 GOwnPtr<WebKitNetworkResponse> networkResponse(0); 204 205 // We are adding one more resource to the load, or maybe we are 206 // just redirecting a load. 207 if (redirectResponse.isNull()) 208 static_cast<WebKit::DocumentLoader*>(loader)->increaseLoadCount(identifier); 209 else 210 networkResponse.set(webkit_network_response_new_with_core_response(redirectResponse)); 211 212 WebKitWebView* webView = getViewFromFrame(m_frame); 213 GOwnPtr<gchar> identifierString(toString(identifier)); 214 WebKitWebResource* webResource = webkit_web_view_get_resource(webView, identifierString.get()); 215 GOwnPtr<WebKitNetworkRequest> networkRequest(webkit_network_request_new_with_core_request(request)); 216 217 if (!redirectResponse.isNull()) { 218 // This is a redirect, so we need to update the WebResource's knowledge 219 // of the URI. 220 g_free(webResource->priv->uri); 221 webResource->priv->uri = g_strdup(request.url().string().utf8().data()); 222 } 223 224 g_signal_emit_by_name(webView, "resource-request-starting", m_frame, webResource, networkRequest.get(), networkResponse.get()); 225 226 // Feed any changes back into the ResourceRequest object. 227 SoupMessage* message = webkit_network_request_get_message(networkRequest.get()); 228 if (!message) { 229 request.setURL(KURL(KURL(), String::fromUTF8(webkit_network_request_get_uri(networkRequest.get())))); 230 return; 231 } 232 233 request.updateFromSoupMessage(message); 234 } 235 236 void FrameLoaderClient::assignIdentifierToInitialRequest(unsigned long identifier, WebCore::DocumentLoader*, const ResourceRequest& request) 237 { 238 webkit_web_view_add_resource(getViewFromFrame(m_frame), toString(identifier), 239 WEBKIT_WEB_RESOURCE(g_object_new(WEBKIT_TYPE_WEB_RESOURCE, "uri", request.url().string().utf8().data(), 0))); 240 } 241 242 void FrameLoaderClient::postProgressStartedNotification() 243 { 244 WebKitWebView* webView = getViewFromFrame(m_frame); 245 g_signal_emit_by_name(webView, "load-started", m_frame); 246 247 g_object_notify(G_OBJECT(webView), "progress"); 248 } 249 250 void FrameLoaderClient::postProgressEstimateChangedNotification() 251 { 252 WebKitWebView* webView = getViewFromFrame(m_frame); 253 Page* corePage = core(webView); 254 255 g_signal_emit_by_name(webView, "load-progress-changed", lround(corePage->progress()->estimatedProgress()*100)); 256 257 g_object_notify(G_OBJECT(webView), "progress"); 258 } 259 260 void FrameLoaderClient::postProgressFinishedNotification() 261 { 262 WebKitWebView* webView = getViewFromFrame(m_frame); 263 WebKitWebViewPrivate* privateData = WEBKIT_WEB_VIEW_GET_PRIVATE(webView); 264 265 // We can get a stopLoad() from dispose when the object is being 266 // destroyed, don't emit the signal in that case. 267 if (!privateData->disposing) 268 g_signal_emit_by_name(webView, "load-finished", m_frame); 269 } 270 271 void FrameLoaderClient::frameLoaderDestroyed() 272 { 273 webkit_web_frame_core_frame_gone(m_frame); 274 g_object_unref(m_frame); 275 m_frame = 0; 276 delete this; 277 } 278 279 void FrameLoaderClient::dispatchDidReceiveResponse(WebCore::DocumentLoader*, unsigned long, const ResourceResponse& response) 280 { 281 m_response = response; 282 } 283 284 void FrameLoaderClient::dispatchDecidePolicyForMIMEType(FramePolicyFunction policyFunction, const String& mimeType, const ResourceRequest& resourceRequest) 285 { 286 ASSERT(policyFunction); 287 if (!policyFunction) 288 return; 289 290 if (resourceRequest.isNull()) { 291 (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyIgnore); 292 return; 293 } 294 295 WebKitWebView* page = getViewFromFrame(m_frame); 296 WebKitNetworkRequest* request = webkit_network_request_new_with_core_request(resourceRequest); 297 298 WebKitWebPolicyDecision* policyDecision = webkit_web_policy_decision_new(m_frame, policyFunction); 299 if (m_policyDecision) 300 g_object_unref(m_policyDecision); 301 m_policyDecision = policyDecision; 302 303 gboolean isHandled = false; 304 g_signal_emit_by_name(page, "mime-type-policy-decision-requested", m_frame, request, mimeType.utf8().data(), policyDecision, &isHandled); 305 306 g_object_unref(request); 307 308 if (isHandled) 309 return; 310 311 GOwnPtr<WebKitNetworkResponse> networkResponse(webkit_web_frame_get_network_response(m_frame)); 312 if (networkResponse) { 313 ResourceResponse response = core(networkResponse.get()); 314 if (response.isAttachment()) { 315 webkit_web_policy_decision_download(policyDecision); 316 return; 317 } 318 } 319 320 if (canShowMIMEType(mimeType)) 321 webkit_web_policy_decision_use(policyDecision); 322 else 323 webkit_web_policy_decision_ignore(policyDecision); 324 } 325 326 static WebKitWebNavigationAction* getNavigationAction(const NavigationAction& action, const char* targetFrame) 327 { 328 gint button = -1; 329 330 const Event* event = action.event(); 331 if (event && event->isMouseEvent()) { 332 const MouseEvent* mouseEvent = static_cast<const MouseEvent*>(event); 333 // DOM button values are 0, 1 and 2 for left, middle and right buttons. 334 // GTK+ uses 1, 2 and 3, so let's add 1 to remain consistent. 335 button = mouseEvent->button() + 1; 336 } 337 338 gint modifierFlags = 0; 339 UIEventWithKeyState* keyStateEvent = findEventWithKeyState(const_cast<Event*>(event)); 340 if (keyStateEvent) { 341 if (keyStateEvent->shiftKey()) 342 modifierFlags |= GDK_SHIFT_MASK; 343 if (keyStateEvent->ctrlKey()) 344 modifierFlags |= GDK_CONTROL_MASK; 345 if (keyStateEvent->altKey()) 346 modifierFlags |= GDK_MOD1_MASK; 347 if (keyStateEvent->metaKey()) 348 modifierFlags |= GDK_MOD2_MASK; 349 } 350 351 return WEBKIT_WEB_NAVIGATION_ACTION(g_object_new(WEBKIT_TYPE_WEB_NAVIGATION_ACTION, 352 "reason", kit(action.type()), 353 "original-uri", action.url().string().utf8().data(), 354 "button", button, 355 "modifier-state", modifierFlags, 356 "target-frame", targetFrame, 357 NULL)); 358 } 359 360 void FrameLoaderClient::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction policyFunction, const NavigationAction& action, const ResourceRequest& resourceRequest, PassRefPtr<FormState>, const String& frameName) 361 { 362 ASSERT(policyFunction); 363 if (!policyFunction) 364 return; 365 366 if (resourceRequest.isNull()) { 367 (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyIgnore); 368 return; 369 } 370 371 WebKitWebPolicyDecision* policyDecision = webkit_web_policy_decision_new(m_frame, policyFunction); 372 373 if (m_policyDecision) 374 g_object_unref(m_policyDecision); 375 m_policyDecision = policyDecision; 376 377 WebKitWebView* webView = getViewFromFrame(m_frame); 378 WebKitNetworkRequest* request = webkit_network_request_new(resourceRequest.url().string().utf8().data()); 379 WebKitWebNavigationAction* navigationAction = getNavigationAction(action, frameName.utf8().data()); 380 gboolean isHandled = false; 381 382 g_signal_emit_by_name(webView, "new-window-policy-decision-requested", m_frame, request, navigationAction, policyDecision, &isHandled); 383 384 g_object_unref(navigationAction); 385 g_object_unref(request); 386 387 // FIXME: I think Qt version marshals this to another thread so when we 388 // have multi-threaded download, we might need to do the same 389 if (!isHandled) 390 (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyUse); 391 } 392 393 void FrameLoaderClient::dispatchDecidePolicyForNavigationAction(FramePolicyFunction policyFunction, const NavigationAction& action, const ResourceRequest& resourceRequest, PassRefPtr<FormState>) 394 { 395 ASSERT(policyFunction); 396 if (!policyFunction) 397 return; 398 399 if (resourceRequest.isNull()) { 400 (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyIgnore); 401 return; 402 } 403 404 WebKitWebView* webView = getViewFromFrame(m_frame); 405 WebKitNetworkRequest* request = webkit_network_request_new_with_core_request(resourceRequest); 406 WebKitNavigationResponse response; 407 /* 408 * We still support the deprecated navigation-requested signal, if the 409 * application doesn't ignore the navigation then the new signal is 410 * emitted. 411 * navigation-policy-decision-requested must be emitted after 412 * navigation-requested as the policy decision can be async. 413 */ 414 g_signal_emit_by_name(webView, "navigation-requested", m_frame, request, &response); 415 416 if (response == WEBKIT_NAVIGATION_RESPONSE_IGNORE) { 417 (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyIgnore); 418 g_object_unref(request); 419 return; 420 } 421 422 WebKitWebPolicyDecision* policyDecision = webkit_web_policy_decision_new(m_frame, policyFunction); 423 if (m_policyDecision) 424 g_object_unref(m_policyDecision); 425 m_policyDecision = policyDecision; 426 427 WebKitWebNavigationAction* navigationAction = getNavigationAction(action, NULL); 428 gboolean isHandled = false; 429 g_signal_emit_by_name(webView, "navigation-policy-decision-requested", m_frame, request, navigationAction, policyDecision, &isHandled); 430 431 g_object_unref(navigationAction); 432 g_object_unref(request); 433 434 // FIXME Implement default behavior when we can query the backend what protocols it supports 435 if (!isHandled) 436 webkit_web_policy_decision_use(m_policyDecision); 437 } 438 439 PassRefPtr<Widget> FrameLoaderClient::createPlugin(const IntSize& pluginSize, HTMLPlugInElement* element, const KURL& url, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually) 440 { 441 /* Check if we want to embed a GtkWidget, fallback to plugins later */ 442 CString urlString = url.string().utf8(); 443 CString mimeTypeString = mimeType.utf8(); 444 445 ASSERT(paramNames.size() == paramValues.size()); 446 GRefPtr<GHashTable> hash = adoptGRef(g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free)); 447 for (unsigned i = 0; i < paramNames.size(); ++i) { 448 g_hash_table_insert(hash.get(), 449 g_strdup(paramNames[i].utf8().data()), 450 g_strdup(paramValues[i].utf8().data())); 451 } 452 453 GtkWidget* gtkWidget = 0; 454 g_signal_emit_by_name(getViewFromFrame(m_frame), "create-plugin-widget", 455 mimeTypeString.data(), urlString.data(), hash.get(), >kWidget); 456 if (gtkWidget) 457 return adoptRef(new GtkPluginWidget(gtkWidget)); 458 459 RefPtr<PluginView> pluginView = PluginView::create(core(m_frame), pluginSize, element, url, paramNames, paramValues, mimeType, loadManually); 460 461 if (pluginView->status() == PluginStatusLoadedSuccessfully) 462 return pluginView; 463 464 return 0; 465 } 466 467 PassRefPtr<Frame> FrameLoaderClient::createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement, 468 const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight) 469 { 470 Frame* coreFrame = core(m_frame); 471 472 ASSERT(core(getViewFromFrame(m_frame)) == coreFrame->page()); 473 474 RefPtr<Frame> childFrame = webkit_web_frame_init_with_web_view(getViewFromFrame(m_frame), ownerElement); 475 476 coreFrame->tree()->appendChild(childFrame); 477 478 childFrame->tree()->setName(name); 479 childFrame->init(); 480 481 // The creation of the frame may have run arbitrary JavaScript that removed it from the page already. 482 if (!childFrame->page()) 483 return 0; 484 485 childFrame->loader()->loadURLIntoChildFrame(url, referrer, childFrame.get()); 486 487 // The frame's onload handler may have removed it from the document. 488 if (!childFrame->tree()->parent()) 489 return 0; 490 491 return childFrame.release(); 492 } 493 494 void FrameLoaderClient::redirectDataToPlugin(Widget* pluginWidget) 495 { 496 ASSERT(!m_pluginView); 497 m_pluginView = static_cast<PluginView*>(pluginWidget); 498 m_hasSentResponseToPlugin = false; 499 } 500 501 PassRefPtr<Widget> FrameLoaderClient::createJavaAppletWidget(const IntSize&, HTMLAppletElement*, const KURL& baseURL, 502 const Vector<String>& paramNames, const Vector<String>& paramValues) 503 { 504 notImplemented(); 505 return 0; 506 } 507 508 ObjectContentType FrameLoaderClient::objectContentType(const KURL& url, const String& mimeType) 509 { 510 return FrameLoader::defaultObjectContentType(url, mimeType); 511 } 512 513 String FrameLoaderClient::overrideMediaType() const 514 { 515 notImplemented(); 516 return String(); 517 } 518 519 void FrameLoaderClient::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld* world) 520 { 521 if (world != mainThreadNormalWorld()) 522 return; 523 524 // Is this obsolete now? 525 g_signal_emit_by_name(m_frame, "cleared"); 526 527 Frame* coreFrame = core(m_frame); 528 ASSERT(coreFrame); 529 530 Settings* settings = coreFrame->settings(); 531 if (!settings || !settings->isJavaScriptEnabled()) 532 return; 533 534 // TODO: Consider using g_signal_has_handler_pending() to avoid the overhead 535 // when there are no handlers. 536 JSGlobalContextRef context = toGlobalRef(coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec()); 537 JSObjectRef windowObject = toRef(coreFrame->script()->globalObject(mainThreadNormalWorld())); 538 ASSERT(windowObject); 539 540 WebKitWebView* webView = getViewFromFrame(m_frame); 541 g_signal_emit_by_name(webView, "window-object-cleared", m_frame, context, windowObject); 542 543 // TODO: Re-attach debug clients if present. 544 // The Win port has an example of how we might do this. 545 } 546 547 void FrameLoaderClient::documentElementAvailable() 548 { 549 } 550 551 void FrameLoaderClient::didPerformFirstNavigation() const 552 { 553 } 554 555 void FrameLoaderClient::registerForIconNotification(bool shouldRegister) 556 { 557 notImplemented(); 558 } 559 560 void FrameLoaderClient::setMainFrameDocumentReady(bool) 561 { 562 // this is only interesting once we provide an external API for the DOM 563 } 564 565 bool FrameLoaderClient::hasWebView() const 566 { 567 return getViewFromFrame(m_frame); 568 } 569 570 void FrameLoaderClient::dispatchDidFinishLoad() 571 { 572 if (m_loadingErrorPage) { 573 m_loadingErrorPage = false; 574 return; 575 } 576 577 loadDone(m_frame, true); 578 } 579 580 void FrameLoaderClient::frameLoadCompleted() 581 { 582 notImplemented(); 583 } 584 585 void FrameLoaderClient::saveViewStateToItem(HistoryItem*) 586 { 587 notImplemented(); 588 } 589 590 void FrameLoaderClient::restoreViewState() 591 { 592 notImplemented(); 593 } 594 595 bool FrameLoaderClient::shouldGoToHistoryItem(HistoryItem* item) const 596 { 597 // FIXME: This is a very simple implementation. More sophisticated 598 // implementation would delegate the decision to a PolicyDelegate. 599 // See mac implementation for example. 600 return item != 0; 601 } 602 603 void FrameLoaderClient::dispatchDidAddBackForwardItem(HistoryItem*) const 604 { 605 } 606 607 void FrameLoaderClient::dispatchDidRemoveBackForwardItem(HistoryItem*) const 608 { 609 } 610 611 void FrameLoaderClient::dispatchDidChangeBackForwardIndex() const 612 { 613 } 614 615 void FrameLoaderClient::didDisplayInsecureContent() 616 { 617 notImplemented(); 618 } 619 620 void FrameLoaderClient::didRunInsecureContent(SecurityOrigin*) 621 { 622 notImplemented(); 623 } 624 625 void FrameLoaderClient::makeRepresentation(WebCore::DocumentLoader*) 626 { 627 notImplemented(); 628 } 629 630 void FrameLoaderClient::forceLayout() 631 { 632 FrameView* view = core(m_frame)->view(); 633 if (view) 634 view->forceLayout(true); 635 } 636 637 void FrameLoaderClient::forceLayoutForNonHTML() 638 { 639 notImplemented(); 640 } 641 642 void FrameLoaderClient::setCopiesOnScroll() 643 { 644 notImplemented(); 645 } 646 647 void FrameLoaderClient::detachedFromParent2() 648 { 649 notImplemented(); 650 } 651 652 void FrameLoaderClient::detachedFromParent3() 653 { 654 notImplemented(); 655 } 656 657 void FrameLoaderClient::dispatchDidHandleOnloadEvents() 658 { 659 notImplemented(); 660 } 661 662 void FrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad() 663 { 664 notImplemented(); 665 } 666 667 void FrameLoaderClient::dispatchDidCancelClientRedirect() 668 { 669 notImplemented(); 670 } 671 672 void FrameLoaderClient::dispatchWillPerformClientRedirect(const KURL&, double, double) 673 { 674 notImplemented(); 675 } 676 677 void FrameLoaderClient::dispatchDidChangeLocationWithinPage() 678 { 679 WebKitWebFramePrivate* priv = m_frame->priv; 680 g_free(priv->uri); 681 priv->uri = g_strdup(core(m_frame)->loader()->url().prettyURL().utf8().data()); 682 g_object_notify(G_OBJECT(m_frame), "uri"); 683 WebKitWebView* webView = getViewFromFrame(m_frame); 684 if (m_frame == webkit_web_view_get_main_frame(webView)) 685 g_object_notify(G_OBJECT(webView), "uri"); 686 } 687 688 void FrameLoaderClient::dispatchDidPushStateWithinPage() 689 { 690 notImplemented(); 691 } 692 693 void FrameLoaderClient::dispatchDidReplaceStateWithinPage() 694 { 695 notImplemented(); 696 } 697 698 void FrameLoaderClient::dispatchDidPopStateWithinPage() 699 { 700 notImplemented(); 701 } 702 703 void FrameLoaderClient::dispatchWillClose() 704 { 705 notImplemented(); 706 } 707 708 void FrameLoaderClient::dispatchDidReceiveIcon() 709 { 710 if (m_loadingErrorPage) 711 return; 712 713 WebKitWebView* webView = getViewFromFrame(m_frame); 714 715 // Avoid reporting favicons for non-main frames. 716 if (m_frame != webkit_web_view_get_main_frame(webView)) 717 return; 718 719 g_object_notify(G_OBJECT(webView), "icon-uri"); 720 g_signal_emit_by_name(webView, "icon-loaded", webkit_web_view_get_icon_uri(webView)); 721 } 722 723 void FrameLoaderClient::dispatchDidStartProvisionalLoad() 724 { 725 if (m_loadingErrorPage) 726 return; 727 728 notifyStatus(m_frame, WEBKIT_LOAD_PROVISIONAL); 729 } 730 731 void FrameLoaderClient::dispatchDidReceiveTitle(const String& title) 732 { 733 if (m_loadingErrorPage) 734 return; 735 736 WebKitWebFramePrivate* priv = m_frame->priv; 737 g_free(priv->title); 738 priv->title = g_strdup(title.utf8().data()); 739 740 g_signal_emit_by_name(m_frame, "title-changed", priv->title); 741 g_object_notify(G_OBJECT(m_frame), "title"); 742 743 WebKitWebView* webView = getViewFromFrame(m_frame); 744 if (m_frame == webkit_web_view_get_main_frame(webView)) { 745 g_signal_emit_by_name(webView, "title-changed", m_frame, title.utf8().data()); 746 g_object_notify(G_OBJECT(webView), "title"); 747 } 748 } 749 750 void FrameLoaderClient::dispatchDidCommitLoad() 751 { 752 if (m_loadingErrorPage) 753 return; 754 755 /* Update the URI once first data has been received. 756 * This means the URI is valid and successfully identify the page that's going to be loaded. 757 */ 758 g_object_freeze_notify(G_OBJECT(m_frame)); 759 760 WebKitWebFramePrivate* priv = m_frame->priv; 761 g_free(priv->uri); 762 priv->uri = g_strdup(core(m_frame)->loader()->activeDocumentLoader()->url().prettyURL().utf8().data()); 763 g_free(priv->title); 764 priv->title = NULL; 765 g_object_notify(G_OBJECT(m_frame), "uri"); 766 g_object_notify(G_OBJECT(m_frame), "title"); 767 768 g_signal_emit_by_name(m_frame, "load-committed"); 769 notifyStatus(m_frame, WEBKIT_LOAD_COMMITTED); 770 771 WebKitWebView* webView = getViewFromFrame(m_frame); 772 if (m_frame == webkit_web_view_get_main_frame(webView)) { 773 g_object_freeze_notify(G_OBJECT(webView)); 774 g_object_notify(G_OBJECT(webView), "uri"); 775 g_object_notify(G_OBJECT(webView), "title"); 776 g_object_thaw_notify(G_OBJECT(webView)); 777 g_signal_emit_by_name(webView, "load-committed", m_frame); 778 } 779 780 g_object_thaw_notify(G_OBJECT(m_frame)); 781 } 782 783 void FrameLoaderClient::dispatchDidFinishDocumentLoad() 784 { 785 notImplemented(); 786 } 787 788 void FrameLoaderClient::dispatchDidFirstLayout() 789 { 790 notImplemented(); 791 } 792 793 void FrameLoaderClient::dispatchDidFirstVisuallyNonEmptyLayout() 794 { 795 if (m_loadingErrorPage) 796 return; 797 798 notifyStatus(m_frame, WEBKIT_LOAD_FIRST_VISUALLY_NON_EMPTY_LAYOUT); 799 } 800 801 void FrameLoaderClient::dispatchShow() 802 { 803 WebKitWebView* webView = getViewFromFrame(m_frame); 804 webkit_web_view_notify_ready(webView); 805 } 806 807 void FrameLoaderClient::cancelPolicyCheck() 808 { 809 //FIXME Add support for more than one policy decision at once 810 if (m_policyDecision) 811 webkit_web_policy_decision_cancel(m_policyDecision); 812 } 813 814 void FrameLoaderClient::dispatchDidLoadMainResource(WebCore::DocumentLoader*) 815 { 816 notImplemented(); 817 } 818 819 void FrameLoaderClient::revertToProvisionalState(WebCore::DocumentLoader*) 820 { 821 notImplemented(); 822 } 823 824 void FrameLoaderClient::willChangeTitle(WebCore::DocumentLoader*) 825 { 826 notImplemented(); 827 } 828 829 void FrameLoaderClient::didChangeTitle(WebCore::DocumentLoader *l) 830 { 831 setTitle(l->title(), l->url()); 832 } 833 834 bool FrameLoaderClient::canHandleRequest(const ResourceRequest&) const 835 { 836 notImplemented(); 837 return true; 838 } 839 840 bool FrameLoaderClient::canShowMIMEType(const String& type) const 841 { 842 return (MIMETypeRegistry::isSupportedImageMIMEType(type) 843 || MIMETypeRegistry::isSupportedNonImageMIMEType(type) 844 || MIMETypeRegistry::isSupportedMediaMIMEType(type) 845 || PluginDatabase::installedPlugins()->isMIMETypeRegistered(type)); 846 } 847 848 bool FrameLoaderClient::representationExistsForURLScheme(const String&) const 849 { 850 notImplemented(); 851 return false; 852 } 853 854 String FrameLoaderClient::generatedMIMETypeForURLScheme(const String&) const 855 { 856 notImplemented(); 857 return String(); 858 } 859 860 void FrameLoaderClient::finishedLoading(WebCore::DocumentLoader* documentLoader) 861 { 862 if (!m_pluginView) { 863 FrameLoader* loader = documentLoader->frameLoader(); 864 loader->setEncoding(m_response.textEncodingName(), false); 865 } else { 866 m_pluginView->didFinishLoading(); 867 m_pluginView = 0; 868 m_hasSentResponseToPlugin = false; 869 } 870 } 871 872 873 void FrameLoaderClient::provisionalLoadStarted() 874 { 875 WebKitWebView* webView = getViewFromFrame(m_frame); 876 877 if (m_frame == webkit_web_view_get_main_frame(webView)) 878 webkit_web_view_clear_resources(webView); 879 } 880 881 void FrameLoaderClient::didFinishLoad() { 882 notImplemented(); 883 } 884 885 void FrameLoaderClient::prepareForDataSourceReplacement() { notImplemented(); } 886 887 void FrameLoaderClient::setTitle(const String& title, const KURL& url) 888 { 889 WebKitWebFramePrivate* frameData = WEBKIT_WEB_FRAME_GET_PRIVATE(m_frame); 890 g_free(frameData->title); 891 frameData->title = g_strdup(title.utf8().data()); 892 } 893 894 void FrameLoaderClient::dispatchDidReceiveContentLength(WebCore::DocumentLoader*, unsigned long identifier, int lengthReceived) 895 { 896 notImplemented(); 897 } 898 899 void FrameLoaderClient::dispatchDidFinishLoading(WebCore::DocumentLoader* loader, unsigned long identifier) 900 { 901 static_cast<WebKit::DocumentLoader*>(loader)->decreaseLoadCount(identifier); 902 903 WebKitWebView* webView = getViewFromFrame(m_frame); 904 GOwnPtr<gchar> identifierString(toString(identifier)); 905 WebKitWebResource* webResource = webkit_web_view_get_resource(webView, identifierString.get()); 906 907 // A NULL WebResource means the load has been interrupted, and 908 // replaced by another one while this resource was being loaded. 909 if (!webResource) 910 return; 911 912 const char* uri = webkit_web_resource_get_uri(webResource); 913 RefPtr<ArchiveResource> coreResource(loader->subresource(KURL(KURL(), uri))); 914 915 // If coreResource is NULL here, the resource failed to load, 916 // unless it's the main resource. 917 if (!coreResource && webResource != webkit_web_view_get_main_resource(webView)) 918 return; 919 920 if (!coreResource) 921 coreResource = loader->mainResource().releaseRef(); 922 923 webkit_web_resource_init_with_core_resource(webResource, coreResource.get()); 924 925 // FIXME: This function should notify the application that the resource 926 // finished loading, maybe using a load-status property in the 927 // WebKitWebResource object, similar to what we do for WebKitWebFrame' 928 // signal. 929 notImplemented(); 930 } 931 932 void FrameLoaderClient::dispatchDidFailLoading(WebCore::DocumentLoader* loader, unsigned long identifier, const ResourceError& error) 933 { 934 static_cast<WebKit::DocumentLoader*>(loader)->decreaseLoadCount(identifier); 935 936 // FIXME: This function should notify the application that the resource failed 937 // loading, maybe a 'load-error' signal in the WebKitWebResource object. 938 notImplemented(); 939 } 940 941 void FrameLoaderClient::dispatchDidLoadResourceByXMLHttpRequest(unsigned long, const ScriptString&) 942 { 943 notImplemented(); 944 } 945 946 bool FrameLoaderClient::dispatchDidLoadResourceFromMemoryCache(WebCore::DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int length) 947 { 948 notImplemented(); 949 return false; 950 } 951 952 void FrameLoaderClient::dispatchDidFailProvisionalLoad(const ResourceError& error) 953 { 954 dispatchDidFailLoad(error); 955 } 956 957 void FrameLoaderClient::dispatchDidFailLoad(const ResourceError& error) 958 { 959 if (m_loadingErrorPage) 960 return; 961 962 notifyStatus(m_frame, WEBKIT_LOAD_FAILED); 963 964 WebKitWebView* webView = getViewFromFrame(m_frame); 965 GError* webError = g_error_new_literal(g_quark_from_string(error.domain().utf8().data()), 966 error.errorCode(), 967 error.localizedDescription().utf8().data()); 968 gboolean isHandled = false; 969 g_signal_emit_by_name(webView, "load-error", m_frame, error.failingURL().utf8().data(), webError, &isHandled); 970 971 if (isHandled) { 972 g_error_free(webError); 973 return; 974 } 975 976 if (!shouldFallBack(error)) { 977 g_error_free(webError); 978 return; 979 } 980 981 m_loadingErrorPage = true; 982 983 String content; 984 gchar* fileContent = 0; 985 gchar* errorURI = g_filename_to_uri(DATA_DIR"/webkit-1.0/resources/error.html", NULL, NULL); 986 GFile* errorFile = g_file_new_for_uri(errorURI); 987 g_free(errorURI); 988 989 if (!errorFile) 990 content = String::format("<html><body>%s</body></html>", webError->message); 991 else { 992 gboolean loaded = g_file_load_contents(errorFile, 0, &fileContent, 0, 0, 0); 993 if (!loaded) 994 content = String::format("<html><body>%s</body></html>", webError->message); 995 else 996 content = String::format(fileContent, error.failingURL().utf8().data(), webError->message); 997 } 998 999 webkit_web_frame_load_alternate_string(m_frame, content.utf8().data(), 0, error.failingURL().utf8().data()); 1000 1001 g_free(fileContent); 1002 1003 if (errorFile) 1004 g_object_unref(errorFile); 1005 1006 g_error_free(webError); 1007 } 1008 1009 void FrameLoaderClient::download(ResourceHandle* handle, const ResourceRequest& request, const ResourceRequest&, const ResourceResponse& response) 1010 { 1011 WebKitNetworkRequest* networkRequest = webkit_network_request_new_with_core_request(request); 1012 WebKitWebView* view = getViewFromFrame(m_frame); 1013 1014 webkit_web_view_request_download(view, networkRequest, response, handle); 1015 g_object_unref(networkRequest); 1016 } 1017 1018 ResourceError FrameLoaderClient::cancelledError(const ResourceRequest& request) 1019 { 1020 return ResourceError(g_quark_to_string(WEBKIT_NETWORK_ERROR), WEBKIT_NETWORK_ERROR_CANCELLED, 1021 request.url().string(), _("Load request cancelled")); 1022 } 1023 1024 ResourceError FrameLoaderClient::blockedError(const ResourceRequest& request) 1025 { 1026 return ResourceError(g_quark_to_string(WEBKIT_POLICY_ERROR), WEBKIT_POLICY_ERROR_CANNOT_USE_RESTRICTED_PORT, 1027 request.url().string(), _("Not allowed to use restricted network port")); 1028 } 1029 1030 ResourceError FrameLoaderClient::cannotShowURLError(const ResourceRequest& request) 1031 { 1032 return ResourceError(g_quark_to_string(WEBKIT_POLICY_ERROR), WEBKIT_POLICY_ERROR_CANNOT_SHOW_URL, 1033 request.url().string(), _("URL cannot be shown")); 1034 } 1035 1036 ResourceError FrameLoaderClient::interruptForPolicyChangeError(const ResourceRequest& request) 1037 { 1038 return ResourceError(g_quark_to_string(WEBKIT_POLICY_ERROR), WEBKIT_POLICY_ERROR_FRAME_LOAD_INTERRUPTED_BY_POLICY_CHANGE, 1039 request.url().string(), _("Frame load was interrupted")); 1040 } 1041 1042 ResourceError FrameLoaderClient::cannotShowMIMETypeError(const ResourceResponse& response) 1043 { 1044 return ResourceError(g_quark_to_string(WEBKIT_POLICY_ERROR), WEBKIT_POLICY_ERROR_CANNOT_SHOW_MIME_TYPE, 1045 response.url().string(), _("Content with the specified MIME type cannot be shown")); 1046 } 1047 1048 ResourceError FrameLoaderClient::fileDoesNotExistError(const ResourceResponse& response) 1049 { 1050 return ResourceError(g_quark_to_string(WEBKIT_NETWORK_ERROR), WEBKIT_NETWORK_ERROR_FILE_DOES_NOT_EXIST, 1051 response.url().string(), _("File does not exist")); 1052 } 1053 1054 ResourceError FrameLoaderClient::pluginWillHandleLoadError(const ResourceResponse& response) 1055 { 1056 return ResourceError(g_quark_to_string(WEBKIT_PLUGIN_ERROR), WEBKIT_PLUGIN_ERROR_WILL_HANDLE_LOAD, 1057 response.url().string(), _("Plugin will handle load")); 1058 } 1059 1060 bool FrameLoaderClient::shouldFallBack(const ResourceError& error) 1061 { 1062 return !(error.isCancellation() || error.errorCode() == WEBKIT_POLICY_ERROR_FRAME_LOAD_INTERRUPTED_BY_POLICY_CHANGE || error.errorCode() == WEBKIT_PLUGIN_ERROR_WILL_HANDLE_LOAD); 1063 } 1064 1065 bool FrameLoaderClient::canCachePage() const 1066 { 1067 return true; 1068 } 1069 1070 Frame* FrameLoaderClient::dispatchCreatePage() 1071 { 1072 WebKitWebView* webView = getViewFromFrame(m_frame); 1073 WebKitWebView* newWebView = 0; 1074 1075 g_signal_emit_by_name(webView, "create-web-view", m_frame, &newWebView); 1076 1077 if (!newWebView) 1078 return 0; 1079 1080 WebKitWebViewPrivate* privateData = WEBKIT_WEB_VIEW_GET_PRIVATE(newWebView); 1081 return core(privateData->mainFrame); 1082 } 1083 1084 void FrameLoaderClient::dispatchUnableToImplementPolicy(const ResourceError&) 1085 { 1086 notImplemented(); 1087 } 1088 1089 void FrameLoaderClient::setMainDocumentError(WebCore::DocumentLoader*, const ResourceError& error) 1090 { 1091 if (m_pluginView) { 1092 m_pluginView->didFail(error); 1093 m_pluginView = 0; 1094 m_hasSentResponseToPlugin = false; 1095 } 1096 } 1097 1098 void FrameLoaderClient::startDownload(const ResourceRequest& request) 1099 { 1100 WebKitNetworkRequest* networkRequest = webkit_network_request_new_with_core_request(request); 1101 WebKitWebView* view = getViewFromFrame(m_frame); 1102 1103 webkit_web_view_request_download(view, networkRequest); 1104 g_object_unref(networkRequest); 1105 } 1106 1107 void FrameLoaderClient::updateGlobalHistory() 1108 { 1109 notImplemented(); 1110 } 1111 1112 void FrameLoaderClient::updateGlobalHistoryRedirectLinks() 1113 { 1114 notImplemented(); 1115 } 1116 1117 void FrameLoaderClient::savePlatformDataToCachedFrame(CachedFrame* cachedFrame) 1118 { 1119 // We need to do this here in order to disconnect the scrollbars 1120 // that are being used by the frame that is being cached from the 1121 // adjustments, otherwise they will react to changes in the 1122 // adjustments, and bad things will happen. 1123 if (cachedFrame->view()) 1124 cachedFrame->view()->setGtkAdjustments(0, 0); 1125 } 1126 1127 static void postCommitFrameViewSetup(WebKitWebFrame *frame, FrameView *view, bool resetValues) 1128 { 1129 WebKitWebView* containingWindow = getViewFromFrame(frame); 1130 WebKitWebViewPrivate* priv = WEBKIT_WEB_VIEW_GET_PRIVATE(containingWindow); 1131 view->setGtkAdjustments(priv->horizontalAdjustment, priv->verticalAdjustment, resetValues); 1132 1133 if (priv->currentMenu) { 1134 GtkMenu* menu = priv->currentMenu; 1135 priv->currentMenu = 0; 1136 1137 gtk_menu_popdown(menu); 1138 g_object_unref(menu); 1139 } 1140 } 1141 1142 void FrameLoaderClient::transitionToCommittedFromCachedFrame(CachedFrame* cachedFrame) 1143 { 1144 ASSERT(cachedFrame->view()); 1145 1146 Frame* frame = core(m_frame); 1147 if (frame != frame->page()->mainFrame()) 1148 return; 1149 1150 postCommitFrameViewSetup(m_frame, cachedFrame->view(), false); 1151 } 1152 1153 void FrameLoaderClient::transitionToCommittedForNewPage() 1154 { 1155 WebKitWebView* containingWindow = getViewFromFrame(m_frame); 1156 IntSize size = IntSize(GTK_WIDGET(containingWindow)->allocation.width, 1157 GTK_WIDGET(containingWindow)->allocation.height); 1158 bool transparent = webkit_web_view_get_transparent(containingWindow); 1159 Color backgroundColor = transparent ? WebCore::Color::transparent : WebCore::Color::white; 1160 Frame* frame = core(m_frame); 1161 ASSERT(frame); 1162 1163 frame->createView(size, backgroundColor, transparent, IntSize(), false); 1164 1165 // We need to do further manipulation on the FrameView if it was the mainFrame 1166 if (frame != frame->page()->mainFrame()) 1167 return; 1168 1169 postCommitFrameViewSetup(m_frame, frame->view(), true); 1170 } 1171 1172 } 1173