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 * Copyright (C) 2010 Igalia S.L. 9 * Copyright (C) 2011 Apple Inc. All rights reserved. 10 * 11 * This library is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU Lesser General Public 13 * License as published by the Free Software Foundation; either 14 * version 2 of the License, or (at your option) any later version. 15 * 16 * This library is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 * Lesser General Public License for more details. 20 * 21 * You should have received a copy of the GNU Lesser General Public 22 * License along with this library; if not, write to the Free Software 23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 24 */ 25 26 #include "config.h" 27 #include "FrameLoaderClientGtk.h" 28 29 #include "AXObjectCache.h" 30 #include "AccessibilityObject.h" 31 #include "ArchiveResource.h" 32 #include "CachedFrame.h" 33 #include "Color.h" 34 #include "DOMObjectCache.h" 35 #include "DocumentLoader.h" 36 #include "DocumentLoaderGtk.h" 37 #include "FormState.h" 38 #include "FrameLoader.h" 39 #include "FrameNetworkingContextGtk.h" 40 #include "FrameTree.h" 41 #include "FrameView.h" 42 #include "GOwnPtr.h" 43 #include "GRefPtr.h" 44 #include "GtkPluginWidget.h" 45 #include "HTMLAppletElement.h" 46 #include "HTMLFormElement.h" 47 #include "HTMLFrameElement.h" 48 #include "HTMLFrameOwnerElement.h" 49 #include "HTMLNames.h" 50 #include "HTMLPlugInElement.h" 51 #include "JSDOMBinding.h" 52 #include "JSDOMWindow.h" 53 #include "Language.h" 54 #include "MIMETypeRegistry.h" 55 #include "MouseEvent.h" 56 #include "NotImplemented.h" 57 #include "Page.h" 58 #include "PluginDatabase.h" 59 #include "ProgressTracker.h" 60 #include "RenderPart.h" 61 #include "RenderView.h" 62 #include "ResourceHandle.h" 63 #include "ResourceRequest.h" 64 #include "ScriptController.h" 65 #include "Settings.h" 66 #include "webkiterror.h" 67 #include "webkitglobals.h" 68 #include "webkitglobalsprivate.h" 69 #include "webkiticondatabase.h" 70 #include "webkitnetworkrequest.h" 71 #include "webkitnetworkrequestprivate.h" 72 #include "webkitnetworkresponse.h" 73 #include "webkitnetworkresponseprivate.h" 74 #include "webkitviewportattributes.h" 75 #include "webkitviewportattributesprivate.h" 76 #include "webkitwebdatasourceprivate.h" 77 #include "webkitwebframe.h" 78 #include "webkitwebframeprivate.h" 79 #include "webkitwebnavigationaction.h" 80 #include "webkitwebnavigationactionprivate.h" 81 #include "webkitwebpolicydecision.h" 82 #include "webkitwebpolicydecisionprivate.h" 83 #include "webkitwebresource.h" 84 #include "webkitwebresourceprivate.h" 85 #include "webkitwebsettingsprivate.h" 86 #include "webkitwebview.h" 87 #include "webkitwebviewprivate.h" 88 #include <JavaScriptCore/APICast.h> 89 #include <gio/gio.h> 90 #include <glib.h> 91 #include <glib/gi18n-lib.h> 92 #include <stdio.h> 93 #include <wtf/text/CString.h> 94 #include <wtf/text/StringConcatenate.h> 95 96 using namespace WebCore; 97 98 namespace WebKit { 99 100 FrameLoaderClient::FrameLoaderClient(WebKitWebFrame* frame) 101 : m_frame(frame) 102 , m_policyDecision(0) 103 , m_loadingErrorPage(false) 104 , m_pluginView(0) 105 , m_hasSentResponseToPlugin(false) 106 , m_hasRepresentation(false) 107 { 108 ASSERT(m_frame); 109 } 110 111 FrameLoaderClient::~FrameLoaderClient() 112 { 113 if (m_policyDecision) 114 g_object_unref(m_policyDecision); 115 } 116 117 static void initializeDomainsList(HashSet<String>& googleDomains) 118 { 119 // Google search domains. 120 googleDomains.add("biz"); 121 googleDomains.add("com"); 122 googleDomains.add("net"); 123 googleDomains.add("org"); 124 googleDomains.add("ae"); 125 googleDomains.add("ag"); 126 googleDomains.add("am"); 127 googleDomains.add("at"); 128 googleDomains.add("az"); 129 googleDomains.add("be"); 130 googleDomains.add("bi"); 131 googleDomains.add("ca"); 132 googleDomains.add("cc"); 133 googleDomains.add("cd"); 134 googleDomains.add("cg"); 135 googleDomains.add("ch"); 136 googleDomains.add("cl"); 137 googleDomains.add("com.br"); 138 googleDomains.add("co.uk"); 139 googleDomains.add("co.kr"); 140 googleDomains.add("co.jp"); 141 googleDomains.add("de"); 142 googleDomains.add("dj"); 143 googleDomains.add("dk"); 144 googleDomains.add("es"); 145 googleDomains.add("fi"); 146 googleDomains.add("fm"); 147 googleDomains.add("fr"); 148 googleDomains.add("gg"); 149 googleDomains.add("gl"); 150 googleDomains.add("gm"); 151 googleDomains.add("gs"); 152 googleDomains.add("hn"); 153 googleDomains.add("hu"); 154 googleDomains.add("ie"); 155 googleDomains.add("it"); 156 googleDomains.add("je"); 157 googleDomains.add("kz"); 158 googleDomains.add("li"); 159 googleDomains.add("lt"); 160 googleDomains.add("lu"); 161 googleDomains.add("lv"); 162 googleDomains.add("ma"); 163 googleDomains.add("ms"); 164 googleDomains.add("mu"); 165 googleDomains.add("mw"); 166 googleDomains.add("nl"); 167 googleDomains.add("no"); 168 googleDomains.add("nu"); 169 googleDomains.add("pl"); 170 googleDomains.add("pn"); 171 googleDomains.add("pt"); 172 googleDomains.add("ru"); 173 googleDomains.add("rw"); 174 googleDomains.add("sh"); 175 googleDomains.add("sk"); 176 googleDomains.add("sm"); 177 googleDomains.add("st"); 178 googleDomains.add("td"); 179 googleDomains.add("tk"); 180 googleDomains.add("tp"); 181 googleDomains.add("tv"); 182 googleDomains.add("us"); 183 googleDomains.add("uz"); 184 googleDomains.add("ws"); 185 } 186 187 static bool isGoogleDomain(String host) 188 { 189 DEFINE_STATIC_LOCAL(HashSet<String>, googleDomains, ()); 190 DEFINE_STATIC_LOCAL(Vector<String>, otherGoogleDomains, ()); 191 192 if (googleDomains.isEmpty()) { 193 otherGoogleDomains.append("gmail.com"); 194 otherGoogleDomains.append("youtube.com"); 195 otherGoogleDomains.append("gstatic.com"); 196 otherGoogleDomains.append("ytimg.com"); 197 198 initializeDomainsList(googleDomains); 199 } 200 201 // First check if this is one of the various google.com international domains. 202 int position = host.find(".google."); 203 if (position > 0 && googleDomains.contains(host.substring(position + sizeof(".google.")))) 204 return true; 205 206 // Then we check the possibility of it being one of the other, .com-only google domains. 207 for (unsigned int i = 0; i < otherGoogleDomains.size(); i++) { 208 if (host.endsWith(otherGoogleDomains.at(i))) 209 return true; 210 } 211 212 return false; 213 } 214 215 String FrameLoaderClient::userAgent(const KURL& url) 216 { 217 WebKitWebSettings* settings = webkit_web_view_get_settings(getViewFromFrame(m_frame)); 218 219 gboolean useQuirks; 220 g_object_get(settings, "enable-site-specific-quirks", &useQuirks, NULL); 221 222 // For Google domains, drop the browser's custom User Agent string, and use the standard 223 // WebKit/Safari one, so they don't give us a broken experience. 224 if (useQuirks && isGoogleDomain(url.host())) 225 return webkitUserAgent(); 226 227 return String::fromUTF8(webkit_web_settings_get_user_agent(settings)); 228 } 229 230 static void notifyAccessibilityStatus(WebKitWebFrame* frame, WebKitLoadStatus loadStatus) 231 { 232 if (loadStatus != WEBKIT_LOAD_PROVISIONAL 233 && loadStatus != WEBKIT_LOAD_FAILED 234 && loadStatus != WEBKIT_LOAD_FINISHED) 235 return; 236 237 WebKitWebFramePrivate* priv = frame->priv; 238 if (!priv->coreFrame || !priv->coreFrame->document()) 239 return; 240 241 RenderView* contentRenderer = priv->coreFrame->contentRenderer(); 242 if (!contentRenderer) 243 return; 244 245 AXObjectCache* axObjectCache = priv->coreFrame->document()->axObjectCache(); 246 if (!axObjectCache) 247 return; 248 249 AccessibilityObject* coreAxObject = axObjectCache->getOrCreate(contentRenderer); 250 if (!coreAxObject) 251 return; 252 253 AtkObject* axObject = coreAxObject->wrapper(); 254 if (!axObject || !ATK_IS_DOCUMENT(axObject)) 255 return; 256 257 switch (loadStatus) { 258 case WEBKIT_LOAD_PROVISIONAL: 259 g_signal_emit_by_name(axObject, "state-change", "busy", true); 260 if (core(frame)->loader()->loadType() == FrameLoadTypeReload) 261 g_signal_emit_by_name(axObject, "reload"); 262 break; 263 case WEBKIT_LOAD_FAILED: 264 g_signal_emit_by_name(axObject, "load-stopped"); 265 g_signal_emit_by_name(axObject, "state-change", "busy", false); 266 break; 267 case WEBKIT_LOAD_FINISHED: 268 g_signal_emit_by_name(axObject, "load-complete"); 269 g_signal_emit_by_name(axObject, "state-change", "busy", false); 270 default: 271 break; 272 } 273 } 274 275 static void notifyStatus(WebKitWebFrame* frame, WebKitLoadStatus loadStatus) 276 { 277 frame->priv->loadStatus = loadStatus; 278 g_object_notify(G_OBJECT(frame), "load-status"); 279 280 WebKitWebView* webView = getViewFromFrame(frame); 281 if (frame == webkit_web_view_get_main_frame(webView)) { 282 webView->priv->loadStatus = loadStatus; 283 g_object_notify(G_OBJECT(webView), "load-status"); 284 285 if (AXObjectCache::accessibilityEnabled()) 286 notifyAccessibilityStatus(frame, loadStatus); 287 } 288 } 289 290 static void loadDone(WebKitWebFrame* frame, bool didSucceed) 291 { 292 // FIXME: load-done is deprecated. Please remove when signal's been removed. 293 g_signal_emit_by_name(frame, "load-done", didSucceed); 294 notifyStatus(frame, WEBKIT_LOAD_FINISHED); 295 } 296 297 WTF::PassRefPtr<WebCore::DocumentLoader> FrameLoaderClient::createDocumentLoader(const WebCore::ResourceRequest& request, const SubstituteData& substituteData) 298 { 299 RefPtr<WebKit::DocumentLoader> loader = WebKit::DocumentLoader::create(request, substituteData); 300 301 GRefPtr<WebKitWebDataSource> webDataSource(adoptGRef(kitNew(loader.get()))); 302 loader->setDataSource(webDataSource.get()); 303 304 return loader.release(); 305 } 306 307 void FrameLoaderClient::dispatchWillSubmitForm(FramePolicyFunction policyFunction, PassRefPtr<FormState>) 308 { 309 // FIXME: This is surely too simple 310 ASSERT(policyFunction); 311 if (!policyFunction) 312 return; 313 (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyUse); 314 } 315 316 void FrameLoaderClient::committedLoad(WebCore::DocumentLoader* loader, const char* data, int length) 317 { 318 if (!m_pluginView) { 319 ASSERT(loader->frame()); 320 loader->commitData(data, length); 321 322 Frame* coreFrame = loader->frame(); 323 if (coreFrame && coreFrame->document()->isMediaDocument()) 324 loader->cancelMainResourceLoad(coreFrame->loader()->client()->pluginWillHandleLoadError(loader->response())); 325 } 326 327 if (m_pluginView) { 328 if (!m_hasSentResponseToPlugin) { 329 m_pluginView->didReceiveResponse(loader->response()); 330 m_hasSentResponseToPlugin = true; 331 } 332 333 // FIXME: We may want to investigate refactoring our plugin loading 334 // code to be similar to mac's. 335 // Also, see http://trac.webkit.org/changeset/24118. 336 if (!m_pluginView) 337 return; 338 339 m_pluginView->didReceiveData(data, length); 340 } 341 } 342 343 bool 344 FrameLoaderClient::shouldUseCredentialStorage(WebCore::DocumentLoader*, unsigned long identifier) 345 { 346 notImplemented(); 347 return false; 348 } 349 350 void FrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(WebCore::DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&) 351 { 352 notImplemented(); 353 } 354 355 void FrameLoaderClient::dispatchDidCancelAuthenticationChallenge(WebCore::DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&) 356 { 357 notImplemented(); 358 } 359 360 // We convert this to string because it's easier to use strings as 361 // keys in a GHashTable. 362 static char* toString(unsigned long identifier) 363 { 364 return g_strdup_printf("%ld", identifier); 365 } 366 367 void FrameLoaderClient::dispatchWillSendRequest(WebCore::DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse) 368 { 369 GRefPtr<WebKitNetworkResponse> networkResponse(0); 370 371 // We are adding one more resource to the load, or maybe we are 372 // just redirecting a load. 373 if (redirectResponse.isNull()) 374 static_cast<WebKit::DocumentLoader*>(loader)->increaseLoadCount(identifier); 375 else 376 networkResponse = adoptGRef(kitNew(redirectResponse)); 377 378 WebKitWebView* webView = getViewFromFrame(m_frame); 379 GOwnPtr<gchar> identifierString(toString(identifier)); 380 WebKitWebResource* webResource = webkit_web_view_get_resource(webView, identifierString.get()); 381 GRefPtr<WebKitNetworkRequest> networkRequest(adoptGRef(kitNew(request))); 382 383 if (!redirectResponse.isNull()) { 384 // This is a redirect, so we need to update the WebResource's knowledge 385 // of the URI. 386 g_free(webResource->priv->uri); 387 webResource->priv->uri = g_strdup(request.url().string().utf8().data()); 388 } 389 390 g_signal_emit_by_name(webView, "resource-request-starting", m_frame, webResource, networkRequest.get(), networkResponse.get()); 391 392 // Feed any changes back into the ResourceRequest object. 393 SoupMessage* message = webkit_network_request_get_message(networkRequest.get()); 394 if (!message) { 395 request.setURL(KURL(KURL(), String::fromUTF8(webkit_network_request_get_uri(networkRequest.get())))); 396 return; 397 } 398 399 request.updateFromSoupMessage(message); 400 } 401 402 void FrameLoaderClient::assignIdentifierToInitialRequest(unsigned long identifier, WebCore::DocumentLoader* loader, const ResourceRequest& request) 403 { 404 GOwnPtr<gchar> identifierString(toString(identifier)); 405 406 WebKitWebResource* webResource = WEBKIT_WEB_RESOURCE(g_object_new(WEBKIT_TYPE_WEB_RESOURCE, "uri", request.url().string().utf8().data(), 0)); 407 408 if (loader == loader->frameLoader()->provisionalDocumentLoader() 409 && loader->frameLoader()->isLoadingMainFrame()) { 410 webkit_web_view_add_main_resource(getViewFromFrame(m_frame), identifierString.get(), webResource); 411 return; 412 } 413 414 webkit_web_view_add_resource(getViewFromFrame(m_frame), identifierString.get(), webResource); 415 } 416 417 void FrameLoaderClient::postProgressStartedNotification() 418 { 419 WebKitWebView* webView = getViewFromFrame(m_frame); 420 g_signal_emit_by_name(webView, "load-started", m_frame); 421 422 g_object_notify(G_OBJECT(webView), "progress"); 423 } 424 425 void FrameLoaderClient::postProgressEstimateChangedNotification() 426 { 427 WebKitWebView* webView = getViewFromFrame(m_frame); 428 Page* corePage = core(webView); 429 430 g_signal_emit_by_name(webView, "load-progress-changed", lround(corePage->progress()->estimatedProgress()*100)); 431 432 g_object_notify(G_OBJECT(webView), "progress"); 433 } 434 435 void FrameLoaderClient::postProgressFinishedNotification() 436 { 437 WebKitWebView* webView = getViewFromFrame(m_frame); 438 WebKitWebViewPrivate* privateData = webView->priv; 439 440 // We can get a stopLoad() from dispose when the object is being 441 // destroyed, don't emit the signal in that case. 442 if (!privateData->disposing) 443 g_signal_emit_by_name(webView, "load-finished", m_frame); 444 } 445 446 void FrameLoaderClient::frameLoaderDestroyed() 447 { 448 webkit_web_frame_core_frame_gone(m_frame); 449 g_object_unref(m_frame); 450 m_frame = 0; 451 delete this; 452 } 453 454 void FrameLoaderClient::dispatchDidReceiveResponse(WebCore::DocumentLoader* loader, unsigned long, const ResourceResponse& response) 455 { 456 // Update our knowledge of request soup flags - some are only set 457 // after the request is done. 458 loader->request().setSoupMessageFlags(response.soupMessageFlags()); 459 460 m_response = response; 461 } 462 463 void FrameLoaderClient::dispatchDecidePolicyForResponse(FramePolicyFunction policyFunction, const ResourceResponse& response, const ResourceRequest& resourceRequest) 464 { 465 ASSERT(policyFunction); 466 if (!policyFunction) 467 return; 468 469 if (resourceRequest.isNull()) { 470 (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyIgnore); 471 return; 472 } 473 474 WebKitWebView* page = getViewFromFrame(m_frame); 475 GRefPtr<WebKitNetworkRequest> request(adoptGRef(kitNew(resourceRequest))); 476 477 WebKitWebPolicyDecision* policyDecision = webkit_web_policy_decision_new(m_frame, policyFunction); 478 if (m_policyDecision) 479 g_object_unref(m_policyDecision); 480 m_policyDecision = policyDecision; 481 482 String mimeType = response.mimeType(); 483 484 gboolean isHandled = false; 485 g_signal_emit_by_name(page, "mime-type-policy-decision-requested", m_frame, request.get(), mimeType.utf8().data(), policyDecision, &isHandled); 486 487 if (isHandled) 488 return; 489 490 GRefPtr<WebKitNetworkResponse> networkResponse(adoptGRef(webkit_web_frame_get_network_response(m_frame))); 491 if (networkResponse) { 492 ResourceResponse response = core(networkResponse.get()); 493 if (response.isAttachment()) { 494 webkit_web_policy_decision_download(policyDecision); 495 return; 496 } 497 } 498 499 if (canShowMIMEType(mimeType)) 500 webkit_web_policy_decision_use(policyDecision); 501 else 502 webkit_web_policy_decision_ignore(policyDecision); 503 } 504 505 static WebKitWebNavigationAction* getNavigationAction(const NavigationAction& action, const char* targetFrame) 506 { 507 gint button = -1; 508 509 const Event* event = action.event(); 510 if (event && event->isMouseEvent()) { 511 const MouseEvent* mouseEvent = static_cast<const MouseEvent*>(event); 512 // DOM button values are 0, 1 and 2 for left, middle and right buttons. 513 // GTK+ uses 1, 2 and 3, so let's add 1 to remain consistent. 514 button = mouseEvent->button() + 1; 515 } 516 517 gint modifierFlags = 0; 518 UIEventWithKeyState* keyStateEvent = findEventWithKeyState(const_cast<Event*>(event)); 519 if (keyStateEvent) { 520 if (keyStateEvent->shiftKey()) 521 modifierFlags |= GDK_SHIFT_MASK; 522 if (keyStateEvent->ctrlKey()) 523 modifierFlags |= GDK_CONTROL_MASK; 524 if (keyStateEvent->altKey()) 525 modifierFlags |= GDK_MOD1_MASK; 526 if (keyStateEvent->metaKey()) 527 modifierFlags |= GDK_MOD2_MASK; 528 } 529 530 return WEBKIT_WEB_NAVIGATION_ACTION(g_object_new(WEBKIT_TYPE_WEB_NAVIGATION_ACTION, 531 "reason", kit(action.type()), 532 "original-uri", action.url().string().utf8().data(), 533 "button", button, 534 "modifier-state", modifierFlags, 535 "target-frame", targetFrame, 536 NULL)); 537 } 538 539 void FrameLoaderClient::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction policyFunction, const NavigationAction& action, const ResourceRequest& resourceRequest, PassRefPtr<FormState>, const String& frameName) 540 { 541 ASSERT(policyFunction); 542 if (!policyFunction) 543 return; 544 545 if (resourceRequest.isNull()) { 546 (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyIgnore); 547 return; 548 } 549 550 WebKitWebPolicyDecision* policyDecision = webkit_web_policy_decision_new(m_frame, policyFunction); 551 552 if (m_policyDecision) 553 g_object_unref(m_policyDecision); 554 m_policyDecision = policyDecision; 555 556 WebKitWebView* webView = getViewFromFrame(m_frame); 557 GRefPtr<WebKitNetworkRequest> request(adoptGRef(webkit_network_request_new(resourceRequest.url().string().utf8().data()))); 558 GRefPtr<WebKitWebNavigationAction> navigationAction(adoptGRef(getNavigationAction(action, frameName.utf8().data()))); 559 gboolean isHandled = false; 560 561 g_signal_emit_by_name(webView, "new-window-policy-decision-requested", m_frame, request.get(), navigationAction.get(), policyDecision, &isHandled); 562 563 // FIXME: I think Qt version marshals this to another thread so when we 564 // have multi-threaded download, we might need to do the same 565 if (!isHandled) 566 (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyUse); 567 } 568 569 void FrameLoaderClient::dispatchDecidePolicyForNavigationAction(FramePolicyFunction policyFunction, const NavigationAction& action, const ResourceRequest& resourceRequest, PassRefPtr<FormState>) 570 { 571 ASSERT(policyFunction); 572 if (!policyFunction) 573 return; 574 575 if (resourceRequest.isNull()) { 576 (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyIgnore); 577 return; 578 } 579 580 WebKitWebView* webView = getViewFromFrame(m_frame); 581 GRefPtr<WebKitNetworkRequest> request(adoptGRef(kitNew(resourceRequest))); 582 WebKitNavigationResponse response; 583 /* 584 * We still support the deprecated navigation-requested signal, if the 585 * application doesn't ignore the navigation then the new signal is 586 * emitted. 587 * navigation-policy-decision-requested must be emitted after 588 * navigation-requested as the policy decision can be async. 589 */ 590 g_signal_emit_by_name(webView, "navigation-requested", m_frame, request.get(), &response); 591 592 if (response == WEBKIT_NAVIGATION_RESPONSE_IGNORE) { 593 (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyIgnore); 594 return; 595 } 596 597 WebKitWebPolicyDecision* policyDecision = webkit_web_policy_decision_new(m_frame, policyFunction); 598 if (m_policyDecision) 599 g_object_unref(m_policyDecision); 600 m_policyDecision = policyDecision; 601 602 GRefPtr<WebKitWebNavigationAction> navigationAction(adoptGRef(getNavigationAction(action, 0))); 603 gboolean isHandled = false; 604 g_signal_emit_by_name(webView, "navigation-policy-decision-requested", m_frame, request.get(), navigationAction.get(), policyDecision, &isHandled); 605 606 // FIXME Implement default behavior when we can query the backend what protocols it supports 607 if (!isHandled) 608 webkit_web_policy_decision_use(m_policyDecision); 609 } 610 611 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) 612 { 613 /* Check if we want to embed a GtkWidget, fallback to plugins later */ 614 CString urlString = url.string().utf8(); 615 CString mimeTypeString = mimeType.utf8(); 616 617 ASSERT(paramNames.size() == paramValues.size()); 618 GRefPtr<GHashTable> hash = adoptGRef(g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free)); 619 for (unsigned i = 0; i < paramNames.size(); ++i) { 620 g_hash_table_insert(hash.get(), 621 g_strdup(paramNames[i].utf8().data()), 622 g_strdup(paramValues[i].utf8().data())); 623 } 624 625 GtkWidget* gtkWidget = 0; 626 g_signal_emit_by_name(getViewFromFrame(m_frame), "create-plugin-widget", 627 mimeTypeString.data(), urlString.data(), hash.get(), >kWidget); 628 if (gtkWidget) 629 return adoptRef(new GtkPluginWidget(gtkWidget)); 630 631 RefPtr<PluginView> pluginView = PluginView::create(core(m_frame), pluginSize, element, url, paramNames, paramValues, mimeType, loadManually); 632 633 if (pluginView->status() == PluginStatusLoadedSuccessfully) 634 return pluginView; 635 636 return 0; 637 } 638 639 PassRefPtr<Frame> FrameLoaderClient::createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement, 640 const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight) 641 { 642 ASSERT(m_frame); 643 Frame* parentFrame = core(m_frame); 644 WebKitWebView* webView = getViewFromFrame(m_frame); 645 WebCore::Page* page = core(webView); 646 ASSERT(page == parentFrame->page()); 647 648 WebKitWebFrame* kitFrame = WEBKIT_WEB_FRAME(g_object_new(WEBKIT_TYPE_WEB_FRAME, NULL)); 649 WebKitWebFramePrivate* framePrivate = kitFrame->priv; 650 framePrivate->webView = webView; 651 652 RefPtr<Frame> childFrame = Frame::create(page, ownerElement, new FrameLoaderClient(kitFrame)); 653 framePrivate->coreFrame = childFrame.get(); 654 655 childFrame->tree()->setName(name); 656 parentFrame->tree()->appendChild(childFrame); 657 childFrame->init(); 658 659 // The creation of the frame may have run arbitrary JavaScript that removed it from the page already. 660 if (!childFrame->page()) 661 return 0; 662 663 g_signal_emit_by_name(webView, "frame-created", kitFrame); 664 665 parentFrame->loader()->loadURLIntoChildFrame(url, referrer, childFrame.get()); 666 667 // The frame's onload handler may have removed it from the document. 668 if (!childFrame->tree()->parent()) 669 return 0; 670 671 return childFrame.release(); 672 } 673 674 void FrameLoaderClient::didTransferChildFrameToNewDocument(WebCore::Page*) 675 { 676 ASSERT(m_frame); 677 678 // Update the frame's webview to the new parent's webview. 679 Frame* coreFrame = core(m_frame); 680 WebKitWebView* webView = getViewFromFrame(m_frame); 681 682 Frame* parentCoreFrame = coreFrame->tree()->parent(); 683 WebKitWebFrame* parentKitFrame = kit(parentCoreFrame); 684 WebKitWebView* parentWebView = getViewFromFrame(parentKitFrame); 685 if (webView != parentWebView) 686 m_frame->priv->webView = parentWebView; 687 688 ASSERT(core(getViewFromFrame(m_frame)) == coreFrame->page()); 689 } 690 691 void FrameLoaderClient::transferLoadingResourceFromPage(unsigned long identifier, WebCore::DocumentLoader* docLoader, const WebCore::ResourceRequest& request, WebCore::Page* oldPage) 692 { 693 ASSERT(oldPage != core(m_frame)->page()); 694 695 GOwnPtr<gchar> identifierString(toString(identifier)); 696 ASSERT(!webkit_web_view_get_resource(getViewFromFrame(m_frame), identifierString.get())); 697 698 assignIdentifierToInitialRequest(identifier, docLoader, request); 699 700 webkit_web_view_remove_resource(kit(oldPage), identifierString.get()); 701 } 702 703 void FrameLoaderClient::redirectDataToPlugin(Widget* pluginWidget) 704 { 705 ASSERT(!m_pluginView); 706 m_pluginView = static_cast<PluginView*>(pluginWidget); 707 m_hasSentResponseToPlugin = false; 708 } 709 710 PassRefPtr<Widget> FrameLoaderClient::createJavaAppletWidget(const IntSize& pluginSize, HTMLAppletElement* element, const KURL& baseURL, const Vector<String>& paramNames, const Vector<String>& paramValues) 711 { 712 return FrameLoaderClient::createPlugin(pluginSize, element, baseURL, paramNames, paramValues, "application/x-java-applet", false); 713 } 714 715 ObjectContentType FrameLoaderClient::objectContentType(const KURL& url, const String& mimeType, bool shouldPreferPlugInsForImages) 716 { 717 return FrameLoader::defaultObjectContentType(url, mimeType, shouldPreferPlugInsForImages); 718 } 719 720 String FrameLoaderClient::overrideMediaType() const 721 { 722 notImplemented(); 723 return String(); 724 } 725 726 void FrameLoaderClient::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld* world) 727 { 728 if (world != mainThreadNormalWorld()) 729 return; 730 731 // Is this obsolete now? 732 g_signal_emit_by_name(m_frame, "cleared"); 733 734 Frame* coreFrame = core(m_frame); 735 ASSERT(coreFrame); 736 737 Settings* settings = coreFrame->settings(); 738 if (!settings || !settings->isJavaScriptEnabled()) 739 return; 740 741 // TODO: Consider using g_signal_has_handler_pending() to avoid the overhead 742 // when there are no handlers. 743 JSGlobalContextRef context = toGlobalRef(coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec()); 744 JSObjectRef windowObject = toRef(coreFrame->script()->globalObject(mainThreadNormalWorld())); 745 ASSERT(windowObject); 746 747 WebKitWebView* webView = getViewFromFrame(m_frame); 748 g_signal_emit_by_name(webView, "window-object-cleared", m_frame, context, windowObject); 749 750 // TODO: Re-attach debug clients if present. 751 // The Win port has an example of how we might do this. 752 } 753 754 void FrameLoaderClient::documentElementAvailable() 755 { 756 } 757 758 void FrameLoaderClient::didPerformFirstNavigation() const 759 { 760 WebKitCacheModel cacheModel = webkit_get_cache_model(); 761 // If user agents do not determine the cache model, we use WEBKIT_CACHE_MODEL_WEB_BROWSER by default. 762 if (cacheModel == WEBKIT_CACHE_MODEL_DEFAULT) 763 webkit_set_cache_model(WEBKIT_CACHE_MODEL_WEB_BROWSER); 764 } 765 766 void FrameLoaderClient::registerForIconNotification(bool shouldRegister) 767 { 768 notImplemented(); 769 } 770 771 void FrameLoaderClient::setMainFrameDocumentReady(bool ready) 772 { 773 if (!ready) 774 DOMObjectCache::clearByFrame(core(m_frame)); 775 } 776 777 bool FrameLoaderClient::hasWebView() const 778 { 779 return getViewFromFrame(m_frame); 780 } 781 782 void FrameLoaderClient::dispatchDidFinishLoad() 783 { 784 if (m_loadingErrorPage) { 785 m_loadingErrorPage = false; 786 return; 787 } 788 789 loadDone(m_frame, true); 790 } 791 792 void FrameLoaderClient::frameLoadCompleted() 793 { 794 notImplemented(); 795 } 796 797 void FrameLoaderClient::saveViewStateToItem(HistoryItem*) 798 { 799 notImplemented(); 800 } 801 802 void FrameLoaderClient::restoreViewState() 803 { 804 notImplemented(); 805 } 806 807 bool FrameLoaderClient::shouldGoToHistoryItem(HistoryItem* item) const 808 { 809 // FIXME: This is a very simple implementation. More sophisticated 810 // implementation would delegate the decision to a PolicyDelegate. 811 // See mac implementation for example. 812 return item != 0; 813 } 814 815 bool FrameLoaderClient::shouldStopLoadingForHistoryItem(HistoryItem* item) const 816 { 817 return true; 818 } 819 820 void FrameLoaderClient::dispatchDidAddBackForwardItem(HistoryItem*) const 821 { 822 } 823 824 void FrameLoaderClient::dispatchDidRemoveBackForwardItem(HistoryItem*) const 825 { 826 } 827 828 void FrameLoaderClient::dispatchDidChangeBackForwardIndex() const 829 { 830 } 831 832 void FrameLoaderClient::didDisplayInsecureContent() 833 { 834 notImplemented(); 835 } 836 837 void FrameLoaderClient::didRunInsecureContent(SecurityOrigin*, const KURL&) 838 { 839 notImplemented(); 840 } 841 842 void FrameLoaderClient::makeRepresentation(WebCore::DocumentLoader*) 843 { 844 m_hasRepresentation = true; 845 } 846 847 void FrameLoaderClient::forceLayout() 848 { 849 FrameView* view = core(m_frame)->view(); 850 if (view) 851 view->forceLayout(true); 852 } 853 854 void FrameLoaderClient::forceLayoutForNonHTML() 855 { 856 notImplemented(); 857 } 858 859 void FrameLoaderClient::setCopiesOnScroll() 860 { 861 notImplemented(); 862 } 863 864 void FrameLoaderClient::detachedFromParent2() 865 { 866 notImplemented(); 867 } 868 869 void FrameLoaderClient::detachedFromParent3() 870 { 871 notImplemented(); 872 } 873 874 void FrameLoaderClient::dispatchDidHandleOnloadEvents() 875 { 876 g_signal_emit_by_name(getViewFromFrame(m_frame), "onload-event", m_frame); 877 } 878 879 void FrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad() 880 { 881 notImplemented(); 882 } 883 884 void FrameLoaderClient::dispatchDidCancelClientRedirect() 885 { 886 notImplemented(); 887 } 888 889 void FrameLoaderClient::dispatchWillPerformClientRedirect(const KURL&, double, double) 890 { 891 notImplemented(); 892 } 893 894 void FrameLoaderClient::dispatchDidChangeLocationWithinPage() 895 { 896 WebKitWebFramePrivate* priv = m_frame->priv; 897 g_free(priv->uri); 898 priv->uri = g_strdup(core(m_frame)->document()->url().string().utf8().data()); 899 g_object_notify(G_OBJECT(m_frame), "uri"); 900 WebKitWebView* webView = getViewFromFrame(m_frame); 901 if (m_frame == webkit_web_view_get_main_frame(webView)) 902 g_object_notify(G_OBJECT(webView), "uri"); 903 } 904 905 void FrameLoaderClient::dispatchDidPushStateWithinPage() 906 { 907 notImplemented(); 908 } 909 910 void FrameLoaderClient::dispatchDidReplaceStateWithinPage() 911 { 912 notImplemented(); 913 } 914 915 void FrameLoaderClient::dispatchDidPopStateWithinPage() 916 { 917 notImplemented(); 918 } 919 920 void FrameLoaderClient::dispatchWillClose() 921 { 922 notImplemented(); 923 } 924 925 void FrameLoaderClient::dispatchDidReceiveIcon() 926 { 927 if (m_loadingErrorPage) 928 return; 929 930 const gchar* frameURI = webkit_web_frame_get_uri(m_frame); 931 WebKitIconDatabase* database = webkit_get_icon_database(); 932 g_signal_emit_by_name(database, "icon-loaded", m_frame, frameURI); 933 934 WebKitWebView* webView = getViewFromFrame(m_frame); 935 936 // Avoid reporting favicons for non-main frames. 937 if (m_frame != webkit_web_view_get_main_frame(webView)) 938 return; 939 940 g_object_notify(G_OBJECT(webView), "icon-uri"); 941 g_signal_emit_by_name(webView, "icon-loaded", webkit_web_view_get_icon_uri(webView)); 942 } 943 944 void FrameLoaderClient::dispatchDidStartProvisionalLoad() 945 { 946 if (m_loadingErrorPage) 947 return; 948 949 notifyStatus(m_frame, WEBKIT_LOAD_PROVISIONAL); 950 } 951 952 void FrameLoaderClient::dispatchDidReceiveTitle(const StringWithDirection& title) 953 { 954 if (m_loadingErrorPage) 955 return; 956 957 WebKitWebFramePrivate* priv = m_frame->priv; 958 g_free(priv->title); 959 // FIXME: use direction of title. 960 priv->title = g_strdup(title.string().utf8().data()); 961 962 g_signal_emit_by_name(m_frame, "title-changed", priv->title); 963 g_object_notify(G_OBJECT(m_frame), "title"); 964 965 WebKitWebView* webView = getViewFromFrame(m_frame); 966 if (m_frame == webkit_web_view_get_main_frame(webView)) { 967 g_signal_emit_by_name(webView, "title-changed", m_frame, title.string().utf8().data()); 968 g_object_notify(G_OBJECT(webView), "title"); 969 } 970 } 971 972 void FrameLoaderClient::dispatchDidChangeIcons() 973 { 974 notImplemented(); 975 } 976 977 void FrameLoaderClient::dispatchDidCommitLoad() 978 { 979 if (m_loadingErrorPage) 980 return; 981 982 /* Update the URI once first data has been received. 983 * This means the URI is valid and successfully identify the page that's going to be loaded. 984 */ 985 g_object_freeze_notify(G_OBJECT(m_frame)); 986 987 WebKitWebFramePrivate* priv = m_frame->priv; 988 g_free(priv->uri); 989 priv->uri = g_strdup(core(m_frame)->loader()->activeDocumentLoader()->url().string().utf8().data()); 990 g_free(priv->title); 991 priv->title = NULL; 992 g_object_notify(G_OBJECT(m_frame), "uri"); 993 g_object_notify(G_OBJECT(m_frame), "title"); 994 995 g_signal_emit_by_name(m_frame, "load-committed"); 996 notifyStatus(m_frame, WEBKIT_LOAD_COMMITTED); 997 998 WebKitWebView* webView = getViewFromFrame(m_frame); 999 if (m_frame == webkit_web_view_get_main_frame(webView)) { 1000 g_object_freeze_notify(G_OBJECT(webView)); 1001 g_object_notify(G_OBJECT(webView), "uri"); 1002 g_object_notify(G_OBJECT(webView), "title"); 1003 g_object_thaw_notify(G_OBJECT(webView)); 1004 g_signal_emit_by_name(webView, "load-committed", m_frame); 1005 } 1006 1007 g_object_thaw_notify(G_OBJECT(m_frame)); 1008 } 1009 1010 void FrameLoaderClient::dispatchDidFinishDocumentLoad() 1011 { 1012 WebKitWebView* webView = getViewFromFrame(m_frame); 1013 g_signal_emit_by_name(webView, "document-load-finished", m_frame); 1014 } 1015 1016 void FrameLoaderClient::dispatchDidFirstLayout() 1017 { 1018 notImplemented(); 1019 } 1020 1021 void FrameLoaderClient::dispatchDidFirstVisuallyNonEmptyLayout() 1022 { 1023 if (m_loadingErrorPage) 1024 return; 1025 1026 notifyStatus(m_frame, WEBKIT_LOAD_FIRST_VISUALLY_NON_EMPTY_LAYOUT); 1027 } 1028 1029 void FrameLoaderClient::dispatchShow() 1030 { 1031 WebKitWebView* webView = getViewFromFrame(m_frame); 1032 webkit_web_view_notify_ready(webView); 1033 } 1034 1035 void FrameLoaderClient::cancelPolicyCheck() 1036 { 1037 //FIXME Add support for more than one policy decision at once 1038 if (m_policyDecision) 1039 webkit_web_policy_decision_cancel(m_policyDecision); 1040 } 1041 1042 void FrameLoaderClient::dispatchDidLoadMainResource(WebCore::DocumentLoader*) 1043 { 1044 notImplemented(); 1045 } 1046 1047 void FrameLoaderClient::revertToProvisionalState(WebCore::DocumentLoader*) 1048 { 1049 m_hasRepresentation = true; 1050 } 1051 1052 void FrameLoaderClient::willChangeTitle(WebCore::DocumentLoader*) 1053 { 1054 notImplemented(); 1055 } 1056 1057 void FrameLoaderClient::didChangeTitle(WebCore::DocumentLoader *l) 1058 { 1059 setTitle(l->title(), l->url()); 1060 } 1061 1062 bool FrameLoaderClient::canHandleRequest(const ResourceRequest&) const 1063 { 1064 notImplemented(); 1065 return true; 1066 } 1067 1068 bool FrameLoaderClient::canShowMIMETypeAsHTML(const String& MIMEType) const 1069 { 1070 notImplemented(); 1071 return false; 1072 } 1073 1074 bool FrameLoaderClient::canShowMIMEType(const String& type) const 1075 { 1076 return (MIMETypeRegistry::isSupportedImageMIMEType(type) 1077 || MIMETypeRegistry::isSupportedNonImageMIMEType(type) 1078 || MIMETypeRegistry::isSupportedMediaMIMEType(type) 1079 || PluginDatabase::installedPlugins()->isMIMETypeRegistered(type)); 1080 } 1081 1082 bool FrameLoaderClient::representationExistsForURLScheme(const String&) const 1083 { 1084 notImplemented(); 1085 return false; 1086 } 1087 1088 String FrameLoaderClient::generatedMIMETypeForURLScheme(const String&) const 1089 { 1090 notImplemented(); 1091 return String(); 1092 } 1093 1094 void FrameLoaderClient::finishedLoading(WebCore::DocumentLoader* documentLoader) 1095 { 1096 if (!m_pluginView) { 1097 // This is necessary to create an empty document, 1098 // but it has to be skipped in the provisional phase. 1099 if (m_hasRepresentation) 1100 documentLoader->writer()->setEncoding("", false); 1101 } else { 1102 m_pluginView->didFinishLoading(); 1103 m_pluginView = 0; 1104 m_hasSentResponseToPlugin = false; 1105 } 1106 } 1107 1108 1109 void FrameLoaderClient::provisionalLoadStarted() 1110 { 1111 notImplemented(); 1112 } 1113 1114 void FrameLoaderClient::didFinishLoad() { 1115 notImplemented(); 1116 } 1117 1118 void FrameLoaderClient::prepareForDataSourceReplacement() 1119 { 1120 notImplemented(); 1121 } 1122 1123 void FrameLoaderClient::setTitle(const StringWithDirection& title, const KURL& url) 1124 { 1125 WebKitWebFramePrivate* frameData = m_frame->priv; 1126 g_free(frameData->title); 1127 // FIXME: use direction of title. 1128 frameData->title = g_strdup(title.string().utf8().data()); 1129 } 1130 1131 void FrameLoaderClient::dispatchDidReceiveContentLength(WebCore::DocumentLoader*, unsigned long identifier, int dataLength) 1132 { 1133 notImplemented(); 1134 } 1135 1136 void FrameLoaderClient::dispatchDidFinishLoading(WebCore::DocumentLoader* loader, unsigned long identifier) 1137 { 1138 static_cast<WebKit::DocumentLoader*>(loader)->decreaseLoadCount(identifier); 1139 1140 WebKitWebView* webView = getViewFromFrame(m_frame); 1141 GOwnPtr<gchar> identifierString(toString(identifier)); 1142 WebKitWebResource* webResource = webkit_web_view_get_resource(webView, identifierString.get()); 1143 1144 // A NULL WebResource means the load has been interrupted, and 1145 // replaced by another one while this resource was being loaded. 1146 if (!webResource) 1147 return; 1148 1149 const char* uri = webkit_web_resource_get_uri(webResource); 1150 RefPtr<ArchiveResource> coreResource(loader->subresource(KURL(KURL(), uri))); 1151 1152 // If coreResource is NULL here, the resource failed to load, 1153 // unless it's the main resource. 1154 if (!coreResource && webResource != webkit_web_view_get_main_resource(webView)) 1155 return; 1156 1157 if (!coreResource) 1158 coreResource = loader->mainResource(); 1159 1160 webkit_web_resource_init_with_core_resource(webResource, coreResource.get()); 1161 1162 // FIXME: This function should notify the application that the resource 1163 // finished loading, maybe using a load-status property in the 1164 // WebKitWebResource object, similar to what we do for WebKitWebFrame' 1165 // signal. 1166 notImplemented(); 1167 } 1168 1169 void FrameLoaderClient::dispatchDidFailLoading(WebCore::DocumentLoader* loader, unsigned long identifier, const ResourceError& error) 1170 { 1171 static_cast<WebKit::DocumentLoader*>(loader)->decreaseLoadCount(identifier); 1172 1173 // FIXME: This function should notify the application that the resource failed 1174 // loading, maybe a 'load-error' signal in the WebKitWebResource object. 1175 notImplemented(); 1176 } 1177 1178 bool FrameLoaderClient::dispatchDidLoadResourceFromMemoryCache(WebCore::DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int length) 1179 { 1180 notImplemented(); 1181 return false; 1182 } 1183 1184 void FrameLoaderClient::dispatchDidFailProvisionalLoad(const ResourceError& error) 1185 { 1186 dispatchDidFailLoad(error); 1187 } 1188 1189 void FrameLoaderClient::dispatchDidFailLoad(const ResourceError& error) 1190 { 1191 if (m_loadingErrorPage) 1192 return; 1193 1194 notifyStatus(m_frame, WEBKIT_LOAD_FAILED); 1195 1196 WebKitWebView* webView = getViewFromFrame(m_frame); 1197 GError* webError = g_error_new_literal(g_quark_from_string(error.domain().utf8().data()), 1198 error.errorCode(), 1199 error.localizedDescription().utf8().data()); 1200 gboolean isHandled = false; 1201 g_signal_emit_by_name(webView, "load-error", m_frame, error.failingURL().utf8().data(), webError, &isHandled); 1202 1203 if (isHandled) { 1204 g_error_free(webError); 1205 return; 1206 } 1207 1208 if (!shouldFallBack(error)) { 1209 g_error_free(webError); 1210 return; 1211 } 1212 1213 m_loadingErrorPage = true; 1214 1215 String content; 1216 gchar* fileContent = 0; 1217 gchar* errorURI = g_filename_to_uri(DATA_DIR"/webkit-1.0/resources/error.html", NULL, NULL); 1218 GFile* errorFile = g_file_new_for_uri(errorURI); 1219 g_free(errorURI); 1220 1221 if (!errorFile) 1222 content = makeString("<html><body>", webError->message, "</body></html>"); 1223 else { 1224 gboolean loaded = g_file_load_contents(errorFile, 0, &fileContent, 0, 0, 0); 1225 if (!loaded) 1226 content = makeString("<html><body>", webError->message, "</body></html>"); 1227 else 1228 content = String::format(fileContent, error.failingURL().utf8().data(), webError->message); 1229 } 1230 1231 webkit_web_frame_load_alternate_string(m_frame, content.utf8().data(), 0, error.failingURL().utf8().data()); 1232 1233 g_free(fileContent); 1234 1235 if (errorFile) 1236 g_object_unref(errorFile); 1237 1238 g_error_free(webError); 1239 } 1240 1241 void FrameLoaderClient::download(ResourceHandle* handle, const ResourceRequest& request, const ResourceRequest&, const ResourceResponse& response) 1242 { 1243 GRefPtr<WebKitNetworkRequest> networkRequest(adoptGRef(kitNew(request))); 1244 WebKitWebView* view = getViewFromFrame(m_frame); 1245 1246 webkit_web_view_request_download(view, networkRequest.get(), response, handle); 1247 } 1248 1249 ResourceError FrameLoaderClient::cancelledError(const ResourceRequest& request) 1250 { 1251 return ResourceError(g_quark_to_string(WEBKIT_NETWORK_ERROR), WEBKIT_NETWORK_ERROR_CANCELLED, 1252 request.url().string(), _("Load request cancelled")); 1253 } 1254 1255 ResourceError FrameLoaderClient::blockedError(const ResourceRequest& request) 1256 { 1257 return ResourceError(g_quark_to_string(WEBKIT_POLICY_ERROR), WEBKIT_POLICY_ERROR_CANNOT_USE_RESTRICTED_PORT, 1258 request.url().string(), _("Not allowed to use restricted network port")); 1259 } 1260 1261 ResourceError FrameLoaderClient::cannotShowURLError(const ResourceRequest& request) 1262 { 1263 return ResourceError(g_quark_to_string(WEBKIT_POLICY_ERROR), WEBKIT_POLICY_ERROR_CANNOT_SHOW_URL, 1264 request.url().string(), _("URL cannot be shown")); 1265 } 1266 1267 ResourceError FrameLoaderClient::interruptForPolicyChangeError(const ResourceRequest& request) 1268 { 1269 return ResourceError(g_quark_to_string(WEBKIT_POLICY_ERROR), WEBKIT_POLICY_ERROR_FRAME_LOAD_INTERRUPTED_BY_POLICY_CHANGE, 1270 request.url().string(), _("Frame load was interrupted")); 1271 } 1272 1273 ResourceError FrameLoaderClient::cannotShowMIMETypeError(const ResourceResponse& response) 1274 { 1275 return ResourceError(g_quark_to_string(WEBKIT_POLICY_ERROR), WEBKIT_POLICY_ERROR_CANNOT_SHOW_MIME_TYPE, 1276 response.url().string(), _("Content with the specified MIME type cannot be shown")); 1277 } 1278 1279 ResourceError FrameLoaderClient::fileDoesNotExistError(const ResourceResponse& response) 1280 { 1281 return ResourceError(g_quark_to_string(WEBKIT_NETWORK_ERROR), WEBKIT_NETWORK_ERROR_FILE_DOES_NOT_EXIST, 1282 response.url().string(), _("File does not exist")); 1283 } 1284 1285 ResourceError FrameLoaderClient::pluginWillHandleLoadError(const ResourceResponse& response) 1286 { 1287 return ResourceError(g_quark_to_string(WEBKIT_PLUGIN_ERROR), WEBKIT_PLUGIN_ERROR_WILL_HANDLE_LOAD, 1288 response.url().string(), _("Plugin will handle load")); 1289 } 1290 1291 bool FrameLoaderClient::shouldFallBack(const ResourceError& error) 1292 { 1293 return !(error.isCancellation() || error.errorCode() == WEBKIT_POLICY_ERROR_FRAME_LOAD_INTERRUPTED_BY_POLICY_CHANGE || error.errorCode() == WEBKIT_PLUGIN_ERROR_WILL_HANDLE_LOAD); 1294 } 1295 1296 bool FrameLoaderClient::canCachePage() const 1297 { 1298 return true; 1299 } 1300 1301 Frame* FrameLoaderClient::dispatchCreatePage(const NavigationAction&) 1302 { 1303 WebKitWebView* webView = getViewFromFrame(m_frame); 1304 WebKitWebView* newWebView = 0; 1305 1306 g_signal_emit_by_name(webView, "create-web-view", m_frame, &newWebView); 1307 1308 if (!newWebView) 1309 return 0; 1310 1311 WebKitWebViewPrivate* privateData = newWebView->priv; 1312 return core(privateData->mainFrame); 1313 } 1314 1315 void FrameLoaderClient::dispatchUnableToImplementPolicy(const ResourceError&) 1316 { 1317 notImplemented(); 1318 } 1319 1320 void FrameLoaderClient::setMainDocumentError(WebCore::DocumentLoader*, const ResourceError& error) 1321 { 1322 if (m_pluginView) { 1323 m_pluginView->didFail(error); 1324 m_pluginView = 0; 1325 m_hasSentResponseToPlugin = false; 1326 } 1327 } 1328 1329 void FrameLoaderClient::startDownload(const ResourceRequest& request) 1330 { 1331 GRefPtr<WebKitNetworkRequest> networkRequest(adoptGRef(kitNew(request))); 1332 WebKitWebView* view = getViewFromFrame(m_frame); 1333 1334 webkit_web_view_request_download(view, networkRequest.get()); 1335 } 1336 1337 void FrameLoaderClient::updateGlobalHistory() 1338 { 1339 notImplemented(); 1340 } 1341 1342 void FrameLoaderClient::updateGlobalHistoryRedirectLinks() 1343 { 1344 notImplemented(); 1345 } 1346 1347 void FrameLoaderClient::savePlatformDataToCachedFrame(CachedFrame* cachedFrame) 1348 { 1349 // We need to do this here in order to disconnect the scrollbars 1350 // that are being used by the frame that is being cached from the 1351 // adjustments, otherwise they will react to changes in the 1352 // adjustments, and bad things will happen. 1353 if (cachedFrame->view()) 1354 cachedFrame->view()->setGtkAdjustments(0, 0); 1355 } 1356 1357 static void postCommitFrameViewSetup(WebKitWebFrame *frame, FrameView *view, bool resetValues) 1358 { 1359 WebKitWebView* containingWindow = getViewFromFrame(frame); 1360 webkit_web_view_clear_resources(containingWindow); 1361 1362 WebKitWebViewPrivate* priv = containingWindow->priv; 1363 view->setGtkAdjustments(priv->horizontalAdjustment.get(), priv->verticalAdjustment.get(), resetValues); 1364 1365 // Invalidate the viewport attributes - they will only be valid 1366 // again if the page we're beginning to load now has an 1367 // appropriate viewport meta tag. 1368 containingWindow->priv->viewportAttributes->priv->isValid = FALSE; 1369 g_object_notify(G_OBJECT(containingWindow->priv->viewportAttributes.get()), "valid"); 1370 1371 if (priv->currentMenu) { 1372 gtk_widget_destroy(GTK_WIDGET(priv->currentMenu)); 1373 priv->currentMenu = 0; 1374 } 1375 1376 // Do not allow click counting between main frame loads. 1377 priv->previousClickTime = 0; 1378 } 1379 1380 void FrameLoaderClient::transitionToCommittedFromCachedFrame(CachedFrame* cachedFrame) 1381 { 1382 ASSERT(cachedFrame->view()); 1383 1384 Frame* frame = core(m_frame); 1385 if (frame != frame->page()->mainFrame()) 1386 return; 1387 1388 postCommitFrameViewSetup(m_frame, cachedFrame->view(), false); 1389 } 1390 1391 void FrameLoaderClient::transitionToCommittedForNewPage() 1392 { 1393 WebKitWebView* containingWindow = getViewFromFrame(m_frame); 1394 GtkAllocation allocation; 1395 #if GTK_CHECK_VERSION(2, 18, 0) 1396 gtk_widget_get_allocation(GTK_WIDGET(containingWindow), &allocation); 1397 #else 1398 allocation = GTK_WIDGET(containingWindow)->allocation; 1399 #endif 1400 IntSize size = IntSize(allocation.width, allocation.height); 1401 bool transparent = webkit_web_view_get_transparent(containingWindow); 1402 Color backgroundColor = transparent ? WebCore::Color::transparent : WebCore::Color::white; 1403 Frame* frame = core(m_frame); 1404 ASSERT(frame); 1405 1406 frame->createView(size, backgroundColor, transparent, IntSize(), false); 1407 1408 // We need to do further manipulation on the FrameView if it was the mainFrame 1409 if (frame != frame->page()->mainFrame()) 1410 return; 1411 1412 postCommitFrameViewSetup(m_frame, frame->view(), true); 1413 } 1414 1415 void FrameLoaderClient::didSaveToPageCache() 1416 { 1417 } 1418 1419 void FrameLoaderClient::didRestoreFromPageCache() 1420 { 1421 } 1422 1423 void FrameLoaderClient::dispatchDidBecomeFrameset(bool) 1424 { 1425 } 1426 1427 PassRefPtr<FrameNetworkingContext> FrameLoaderClient::createNetworkingContext() 1428 { 1429 return FrameNetworkingContextGtk::create(core(m_frame)); 1430 } 1431 1432 } 1433