1/*
2 * Copyright (C) 2009, 2012 Google Inc. All rights reserved.
3 * Copyright (C) 2011 Apple Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 *     * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *     * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 *     * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include "config.h"
33#include "FrameLoaderClientImpl.h"
34
35#include "HTMLNames.h"
36#include "core/dom/Document.h"
37#include "core/dom/MessageEvent.h"
38#include "core/dom/MouseEvent.h"
39#include "core/history/HistoryItem.h"
40#include "core/html/HTMLAppletElement.h"
41#include "core/html/HTMLFormElement.h"  // needed by core/loader/FormState.h
42#include "core/loader/DocumentLoader.h"
43#include "core/loader/FormState.h"
44#include "core/loader/FrameLoadRequest.h"
45#include "core/loader/FrameLoader.h"
46#include "core/loader/ProgressTracker.h"
47#include "core/loader/ResourceLoader.h"
48#include "core/page/Chrome.h"
49#include "core/page/EventHandler.h"
50#include "core/page/FrameView.h"
51#include "core/page/Page.h"
52#include "core/platform/MIMETypeRegistry.h"
53#include "core/platform/mediastream/RTCPeerConnectionHandler.h"
54#include "core/platform/network/HTTPParsers.h"
55#include "core/plugins/PluginData.h"
56#include "core/rendering/HitTestResult.h"
57#include <v8.h>
58#include "WebAutofillClient.h"
59#include "WebCachedURLRequest.h"
60#include "WebDOMEvent.h"
61#include "WebDataSourceImpl.h"
62#include "WebDevToolsAgentPrivate.h"
63#include "WebDocument.h"
64#include "WebFormElement.h"
65#include "WebFrameClient.h"
66#include "WebFrameImpl.h"
67#include "WebNode.h"
68#include "WebPermissionClient.h"
69#include "WebPlugin.h"
70#include "WebPluginContainerImpl.h"
71#include "WebPluginLoadObserver.h"
72#include "WebPluginParams.h"
73#include "WebSecurityOrigin.h"
74#include "WebViewClient.h"
75#include "WebViewImpl.h"
76#include "bindings/v8/ScriptController.h"
77#include "core/dom/UserGestureIndicator.h"
78#include "core/page/Settings.h"
79#include "core/page/WindowFeatures.h"
80#include "core/platform/chromium/support/WrappedResourceRequest.h"
81#include "core/platform/chromium/support/WrappedResourceResponse.h"
82#include "core/platform/network/SocketStreamHandleInternal.h"
83#include "public/platform/Platform.h"
84#include "public/platform/WebMimeRegistry.h"
85#include "public/platform/WebSocketStreamHandle.h"
86#include "public/platform/WebURL.h"
87#include "public/platform/WebURLError.h"
88#include "public/platform/WebVector.h"
89#include "wtf/StringExtras.h"
90#include "wtf/text/CString.h"
91#include "wtf/text/WTFString.h"
92
93using namespace WebCore;
94
95namespace WebKit {
96
97// Domain for internal error codes.
98static const char internalErrorDomain[] = "WebKit";
99
100// An internal error code.  Used to note a policy change error resulting from
101// dispatchDecidePolicyForMIMEType not passing the PolicyUse option.
102enum {
103    PolicyChangeError = -10000,
104};
105
106FrameLoaderClientImpl::FrameLoaderClientImpl(WebFrameImpl* frame)
107    : m_webFrame(frame)
108{
109}
110
111FrameLoaderClientImpl::~FrameLoaderClientImpl()
112{
113}
114
115void FrameLoaderClientImpl::frameLoaderDestroyed()
116{
117    // When the WebFrame was created, it had an extra reference given to it on
118    // behalf of the Frame.  Since the WebFrame owns us, this extra ref also
119    // serves to keep us alive until the FrameLoader is done with us.  The
120    // FrameLoader calls this method when it's going away.  Therefore, we balance
121    // out that extra reference, which may cause 'this' to be deleted.
122    ASSERT(!m_webFrame->frame());
123    m_webFrame->deref();
124}
125
126void FrameLoaderClientImpl::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld*)
127{
128    if (m_webFrame->client())
129        m_webFrame->client()->didClearWindowObject(m_webFrame);
130}
131
132void FrameLoaderClientImpl::documentElementAvailable()
133{
134    if (m_webFrame->client())
135        m_webFrame->client()->didCreateDocumentElement(m_webFrame);
136}
137
138void FrameLoaderClientImpl::didExhaustMemoryAvailableForScript()
139{
140    if (m_webFrame->client())
141        m_webFrame->client()->didExhaustMemoryAvailableForScript(m_webFrame);
142}
143
144void FrameLoaderClientImpl::didCreateScriptContext(v8::Handle<v8::Context> context, int extensionGroup, int worldId)
145{
146    WebViewImpl* webview = m_webFrame->viewImpl();
147    if (webview->devToolsAgentPrivate())
148        webview->devToolsAgentPrivate()->didCreateScriptContext(m_webFrame, worldId);
149    if (m_webFrame->client())
150        m_webFrame->client()->didCreateScriptContext(m_webFrame, context, extensionGroup, worldId);
151}
152
153void FrameLoaderClientImpl::willReleaseScriptContext(v8::Handle<v8::Context> context, int worldId)
154{
155    if (m_webFrame->client())
156        m_webFrame->client()->willReleaseScriptContext(m_webFrame, context, worldId);
157}
158
159bool FrameLoaderClientImpl::allowScriptExtension(const String& extensionName,
160                                                 int extensionGroup,
161                                                 int worldId)
162{
163    WebViewImpl* webview = m_webFrame->viewImpl();
164    if (webview && webview->permissionClient())
165        return webview->permissionClient()->allowScriptExtension(m_webFrame, extensionName, extensionGroup, worldId);
166
167    return true;
168}
169
170void FrameLoaderClientImpl::didChangeScrollOffset()
171{
172    if (m_webFrame->client())
173        m_webFrame->client()->didChangeScrollOffset(m_webFrame);
174}
175
176bool FrameLoaderClientImpl::allowScript(bool enabledPerSettings)
177{
178    WebViewImpl* webview = m_webFrame->viewImpl();
179    if (webview && webview->permissionClient())
180        return webview->permissionClient()->allowScript(m_webFrame, enabledPerSettings);
181
182    return enabledPerSettings;
183}
184
185bool FrameLoaderClientImpl::allowScriptFromSource(bool enabledPerSettings, const KURL& scriptURL)
186{
187    WebViewImpl* webview = m_webFrame->viewImpl();
188    if (webview && webview->permissionClient())
189        return webview->permissionClient()->allowScriptFromSource(m_webFrame, enabledPerSettings, scriptURL);
190
191    return enabledPerSettings;
192}
193
194bool FrameLoaderClientImpl::allowPlugins(bool enabledPerSettings)
195{
196    WebViewImpl* webview = m_webFrame->viewImpl();
197    if (webview && webview->permissionClient())
198        return webview->permissionClient()->allowPlugins(m_webFrame, enabledPerSettings);
199
200    return enabledPerSettings;
201}
202
203bool FrameLoaderClientImpl::allowImage(bool enabledPerSettings, const KURL& imageURL)
204{
205    WebViewImpl* webview = m_webFrame->viewImpl();
206    if (webview && webview->permissionClient())
207        return webview->permissionClient()->allowImage(m_webFrame, enabledPerSettings, imageURL);
208
209    return enabledPerSettings;
210}
211
212bool FrameLoaderClientImpl::allowDisplayingInsecureContent(bool enabledPerSettings, SecurityOrigin* context, const KURL& url)
213{
214    WebViewImpl* webview = m_webFrame->viewImpl();
215    if (webview && webview->permissionClient())
216        return webview->permissionClient()->allowDisplayingInsecureContent(m_webFrame, enabledPerSettings, WebSecurityOrigin(context), WebURL(url));
217
218    return enabledPerSettings;
219}
220
221bool FrameLoaderClientImpl::allowRunningInsecureContent(bool enabledPerSettings, SecurityOrigin* context, const KURL& url)
222{
223    WebViewImpl* webview = m_webFrame->viewImpl();
224    if (webview && webview->permissionClient())
225        return webview->permissionClient()->allowRunningInsecureContent(m_webFrame, enabledPerSettings, WebSecurityOrigin(context), WebURL(url));
226
227    return enabledPerSettings;
228}
229
230void FrameLoaderClientImpl::didNotAllowScript()
231{
232    WebViewImpl* webview = m_webFrame->viewImpl();
233    if (webview && webview->permissionClient())
234        webview->permissionClient()->didNotAllowScript(m_webFrame);
235}
236
237void FrameLoaderClientImpl::didNotAllowPlugins()
238{
239    WebViewImpl* webview = m_webFrame->viewImpl();
240    if (webview && webview->permissionClient())
241        webview->permissionClient()->didNotAllowPlugins(m_webFrame);
242
243}
244
245bool FrameLoaderClientImpl::hasWebView() const
246{
247    return m_webFrame->viewImpl();
248}
249
250bool FrameLoaderClientImpl::hasFrameView() const
251{
252    // The Mac port has this notion of a WebFrameView, which seems to be
253    // some wrapper around an NSView.  Since our equivalent is HWND, I guess
254    // we have a "frameview" whenever we have the toplevel HWND.
255    return m_webFrame->viewImpl();
256}
257
258void FrameLoaderClientImpl::detachedFromParent()
259{
260    // Close down the proxy.  The purpose of this change is to make the
261    // call to ScriptController::clearWindowShell a no-op when called from
262    // Frame::pageDestroyed.  Without this change, this call to clearWindowShell
263    // will cause a crash.  If you remove/modify this, just ensure that you can
264    // go to a page and then navigate to a new page without getting any asserts
265    // or crashes.
266    m_webFrame->frame()->script()->clearForClose();
267
268    // Alert the client that the frame is being detached. This is the last
269    // chance we have to communicate with the client.
270    if (m_webFrame->client())
271        m_webFrame->client()->frameDetached(m_webFrame);
272
273    // Stop communicating with the WebFrameClient at this point since we are no
274    // longer associated with the Page.
275    m_webFrame->setClient(0);
276}
277
278void FrameLoaderClientImpl::dispatchWillRequestAfterPreconnect(ResourceRequest& request)
279{
280    if (m_webFrame->client()) {
281        WrappedResourceRequest webreq(request);
282        m_webFrame->client()->willRequestAfterPreconnect(m_webFrame, webreq);
283    }
284}
285
286void FrameLoaderClientImpl::dispatchWillSendRequest(
287    DocumentLoader* loader, unsigned long identifier, ResourceRequest& request,
288    const ResourceResponse& redirectResponse)
289{
290    // Give the WebFrameClient a crack at the request.
291    if (m_webFrame->client()) {
292        WrappedResourceRequest webreq(request);
293        WrappedResourceResponse webresp(redirectResponse);
294        m_webFrame->client()->willSendRequest(
295            m_webFrame, identifier, webreq, webresp);
296    }
297}
298
299void FrameLoaderClientImpl::dispatchDidReceiveResponse(DocumentLoader* loader,
300                                                       unsigned long identifier,
301                                                       const ResourceResponse& response)
302{
303    if (m_webFrame->client()) {
304        WrappedResourceResponse webresp(response);
305        m_webFrame->client()->didReceiveResponse(m_webFrame, identifier, webresp);
306    }
307}
308void FrameLoaderClientImpl::dispatchDidChangeResourcePriority(unsigned long identifier,
309                                                              ResourceLoadPriority priority)
310{
311    if (m_webFrame->client())
312        m_webFrame->client()->didChangeResourcePriority(m_webFrame, identifier, static_cast<WebKit::WebURLRequest::Priority>(priority));
313}
314
315// Called when a particular resource load completes
316void FrameLoaderClientImpl::dispatchDidFinishLoading(DocumentLoader* loader,
317                                                    unsigned long identifier)
318{
319    if (m_webFrame->client())
320        m_webFrame->client()->didFinishResourceLoad(m_webFrame, identifier);
321}
322
323void FrameLoaderClientImpl::dispatchDidFinishDocumentLoad()
324{
325    if (m_webFrame->client())
326        m_webFrame->client()->didFinishDocumentLoad(m_webFrame);
327}
328
329void FrameLoaderClientImpl::dispatchDidLoadResourceFromMemoryCache(
330    DocumentLoader* loader,
331    const ResourceRequest& request,
332    const ResourceResponse& response,
333    int length)
334{
335    if (m_webFrame->client()) {
336        WrappedResourceRequest webreq(request);
337        WrappedResourceResponse webresp(response);
338        m_webFrame->client()->didLoadResourceFromMemoryCache(
339            m_webFrame, webreq, webresp);
340    }
341}
342
343void FrameLoaderClientImpl::dispatchDidHandleOnloadEvents()
344{
345    if (m_webFrame->client())
346        m_webFrame->client()->didHandleOnloadEvents(m_webFrame);
347}
348
349void FrameLoaderClientImpl::dispatchDidReceiveServerRedirectForProvisionalLoad()
350{
351    if (m_webFrame->client())
352        m_webFrame->client()->didReceiveServerRedirectForProvisionalLoad(m_webFrame);
353}
354
355void FrameLoaderClientImpl::dispatchDidNavigateWithinPage()
356{
357    bool isNewNavigation;
358    m_webFrame->viewImpl()->didCommitLoad(&isNewNavigation, true);
359    if (m_webFrame->client())
360        m_webFrame->client()->didNavigateWithinPage(m_webFrame, isNewNavigation);
361}
362
363void FrameLoaderClientImpl::dispatchWillClose()
364{
365    if (m_webFrame->client())
366        m_webFrame->client()->willClose(m_webFrame);
367}
368
369void FrameLoaderClientImpl::dispatchDidStartProvisionalLoad()
370{
371    if (m_webFrame->client())
372        m_webFrame->client()->didStartProvisionalLoad(m_webFrame);
373}
374
375void FrameLoaderClientImpl::dispatchDidReceiveTitle(const StringWithDirection& title)
376{
377    if (m_webFrame->client())
378        m_webFrame->client()->didReceiveTitle(m_webFrame, title.string(), title.direction() == LTR ? WebTextDirectionLeftToRight : WebTextDirectionRightToLeft);
379}
380
381void FrameLoaderClientImpl::dispatchDidChangeIcons(WebCore::IconType type)
382{
383    if (m_webFrame->client())
384        m_webFrame->client()->didChangeIcon(m_webFrame, static_cast<WebIconURL::Type>(type));
385}
386
387void FrameLoaderClientImpl::dispatchDidCommitLoad()
388{
389    WebViewImpl* webview = m_webFrame->viewImpl();
390    bool isNewNavigation;
391    webview->didCommitLoad(&isNewNavigation, false);
392
393    if (m_webFrame->client())
394        m_webFrame->client()->didCommitProvisionalLoad(m_webFrame, isNewNavigation);
395}
396
397void FrameLoaderClientImpl::dispatchDidFailProvisionalLoad(
398    const ResourceError& error)
399{
400
401    // If a policy change occured, then we do not want to inform the plugin
402    // delegate.  See http://b/907789 for details.  FIXME: This means the
403    // plugin won't receive NPP_URLNotify, which seems like it could result in
404    // a memory leak in the plugin!!
405    if (error.domain() == internalErrorDomain
406        && error.errorCode() == PolicyChangeError) {
407        m_webFrame->didFail(ResourceError::cancelledError(error.failingURL()), true);
408        return;
409    }
410
411    OwnPtr<WebPluginLoadObserver> observer = pluginLoadObserver();
412    m_webFrame->didFail(error, true);
413    if (observer)
414        observer->didFailLoading(error);
415}
416
417void FrameLoaderClientImpl::dispatchDidFailLoad(const ResourceError& error)
418{
419    OwnPtr<WebPluginLoadObserver> observer = pluginLoadObserver();
420    m_webFrame->didFail(error, false);
421    if (observer)
422        observer->didFailLoading(error);
423
424    // Don't clear the redirect chain, this will happen in the middle of client
425    // redirects, and we need the context. The chain will be cleared when the
426    // provisional load succeeds or fails, not the "real" one.
427}
428
429void FrameLoaderClientImpl::dispatchDidFinishLoad()
430{
431    OwnPtr<WebPluginLoadObserver> observer = pluginLoadObserver();
432
433    if (m_webFrame->client())
434        m_webFrame->client()->didFinishLoad(m_webFrame);
435
436    if (observer)
437        observer->didFinishLoading();
438
439    // Don't clear the redirect chain, this will happen in the middle of client
440    // redirects, and we need the context. The chain will be cleared when the
441    // provisional load succeeds or fails, not the "real" one.
442}
443
444void FrameLoaderClientImpl::dispatchDidLayout(LayoutMilestones milestones)
445{
446    if (!m_webFrame->client())
447        return;
448
449    if (milestones & DidFirstLayout)
450        m_webFrame->client()->didFirstLayout(m_webFrame);
451    if (milestones & DidFirstVisuallyNonEmptyLayout)
452        m_webFrame->client()->didFirstVisuallyNonEmptyLayout(m_webFrame);
453}
454
455NavigationPolicy FrameLoaderClientImpl::decidePolicyForNavigation(const ResourceRequest& request, DocumentLoader* loader, NavigationPolicy policy)
456{
457    if (!m_webFrame->client())
458        return NavigationPolicyIgnore;
459    WebDataSourceImpl* ds = WebDataSourceImpl::fromDocumentLoader(loader);
460    WebNavigationPolicy webPolicy = m_webFrame->client()->decidePolicyForNavigation(m_webFrame, ds->extraData(), WrappedResourceRequest(request),
461        ds->navigationType(), static_cast<WebNavigationPolicy>(policy), ds->isRedirect());
462    return static_cast<NavigationPolicy>(webPolicy);
463}
464
465bool FrameLoaderClientImpl::shouldAbortNavigationAfterUrlResolve(const KURL& base, const String& fragment, const KURL& result) {
466  if (!m_webFrame->client())
467    return false;
468  return m_webFrame->client()->shouldAbortNavigationAfterUrlResolve(base, fragment, result);
469}
470
471void FrameLoaderClientImpl::dispatchWillRequestResource(FetchRequest* request)
472{
473    if (m_webFrame->client()) {
474        WebCachedURLRequest urlRequest(request);
475        m_webFrame->client()->willRequestResource(m_webFrame, urlRequest);
476    }
477}
478
479void FrameLoaderClientImpl::dispatchWillSendSubmitEvent(PassRefPtr<FormState> prpFormState)
480{
481    if (m_webFrame->client())
482        m_webFrame->client()->willSendSubmitEvent(m_webFrame, WebFormElement(prpFormState->form()));
483}
484
485void FrameLoaderClientImpl::dispatchWillSubmitForm(PassRefPtr<FormState> formState)
486{
487    if (m_webFrame->client())
488        m_webFrame->client()->willSubmitForm(m_webFrame, WebFormElement(formState->form()));
489}
490
491void FrameLoaderClientImpl::postProgressStartedNotification()
492{
493    WebViewImpl* webview = m_webFrame->viewImpl();
494    if (webview && webview->client())
495        webview->client()->didStartLoading();
496}
497
498void FrameLoaderClientImpl::postProgressEstimateChangedNotification()
499{
500    WebViewImpl* webview = m_webFrame->viewImpl();
501    if (webview && webview->client()) {
502        webview->client()->didChangeLoadProgress(
503            m_webFrame, m_webFrame->frame()->page()->progress()->estimatedProgress());
504    }
505}
506
507void FrameLoaderClientImpl::postProgressFinishedNotification()
508{
509    // FIXME: why might the webview be null?  http://b/1234461
510    WebViewImpl* webview = m_webFrame->viewImpl();
511    if (webview && webview->client())
512        webview->client()->didStopLoading();
513}
514
515void FrameLoaderClientImpl::loadURLExternally(const ResourceRequest& request, NavigationPolicy policy, const String& suggestedName)
516{
517    if (m_webFrame->client()) {
518        WrappedResourceRequest webreq(request);
519        m_webFrame->client()->loadURLExternally(
520            m_webFrame, webreq, static_cast<WebNavigationPolicy>(policy), suggestedName);
521    }
522}
523
524bool FrameLoaderClientImpl::shouldGoToHistoryItem(HistoryItem* item) const
525{
526    const KURL& url = item->url();
527    if (!url.protocolIs(backForwardNavigationScheme))
528        return true;
529
530    // Else, we'll punt this history navigation to the embedder.  It is
531    // necessary that we intercept this here, well before the FrameLoader
532    // has made any state changes for this history traversal.
533
534    bool ok;
535    int offset = url.lastPathComponent().toIntStrict(&ok);
536    if (!ok) {
537        ASSERT_NOT_REACHED();
538        return false;
539    }
540
541    WebViewImpl* webview = m_webFrame->viewImpl();
542    if (webview->client())
543        webview->client()->navigateBackForwardSoon(offset);
544
545    return false;
546}
547
548bool FrameLoaderClientImpl::shouldStopLoadingForHistoryItem(HistoryItem* targetItem) const
549{
550    // Don't stop loading for pseudo-back-forward URLs, since they will get
551    // translated and then pass through again.
552    const KURL& url = targetItem->url();
553    return !url.protocolIs(backForwardNavigationScheme);
554}
555
556void FrameLoaderClientImpl::didAccessInitialDocument()
557{
558    if (m_webFrame->client())
559        m_webFrame->client()->didAccessInitialDocument(m_webFrame);
560}
561
562void FrameLoaderClientImpl::didDisownOpener()
563{
564    if (m_webFrame->client())
565        m_webFrame->client()->didDisownOpener(m_webFrame);
566}
567
568void FrameLoaderClientImpl::didDisplayInsecureContent()
569{
570    if (m_webFrame->client())
571        m_webFrame->client()->didDisplayInsecureContent(m_webFrame);
572}
573
574void FrameLoaderClientImpl::didRunInsecureContent(SecurityOrigin* origin, const KURL& insecureURL)
575{
576    if (m_webFrame->client())
577        m_webFrame->client()->didRunInsecureContent(m_webFrame, WebSecurityOrigin(origin), insecureURL);
578}
579
580void FrameLoaderClientImpl::didDetectXSS(const KURL& insecureURL, bool didBlockEntirePage)
581{
582    if (m_webFrame->client())
583        m_webFrame->client()->didDetectXSS(m_webFrame, insecureURL, didBlockEntirePage);
584}
585
586void FrameLoaderClientImpl::didDispatchPingLoader(const KURL& url)
587{
588    if (m_webFrame->client())
589        m_webFrame->client()->didDispatchPingLoader(m_webFrame, url);
590}
591
592ResourceError FrameLoaderClientImpl::interruptedForPolicyChangeError(
593    const ResourceRequest& request)
594{
595    return ResourceError(internalErrorDomain, PolicyChangeError,
596                         request.url().string(), String());
597}
598
599PassRefPtr<DocumentLoader> FrameLoaderClientImpl::createDocumentLoader(
600    const ResourceRequest& request,
601    const SubstituteData& data)
602{
603    RefPtr<WebDataSourceImpl> ds = WebDataSourceImpl::create(request, data);
604    if (m_webFrame->client())
605        m_webFrame->client()->didCreateDataSource(m_webFrame, ds.get());
606    return ds.release();
607}
608
609String FrameLoaderClientImpl::userAgent(const KURL& url)
610{
611    WebString override = m_webFrame->client()->userAgentOverride(m_webFrame, WebURL(url));
612    if (!override.isEmpty())
613        return override;
614
615    return WebKit::Platform::current()->userAgent(url);
616}
617
618String FrameLoaderClientImpl::doNotTrackValue()
619{
620    WebString doNotTrack = m_webFrame->client()->doNotTrackValue(m_webFrame);
621    if (!doNotTrack.isEmpty())
622        return doNotTrack;
623    return String();
624}
625
626// Called when the FrameLoader goes into a state in which a new page load
627// will occur.
628void FrameLoaderClientImpl::transitionToCommittedForNewPage()
629{
630    m_webFrame->createFrameView();
631}
632
633PassRefPtr<Frame> FrameLoaderClientImpl::createFrame(
634    const KURL& url,
635    const String& name,
636    HTMLFrameOwnerElement* ownerElement,
637    const String& referrer,
638    bool allowsScrolling,
639    int marginWidth,
640    int marginHeight)
641{
642    FrameLoadRequest frameRequest(m_webFrame->frame()->document()->securityOrigin(),
643        ResourceRequest(url, referrer), name);
644    return m_webFrame->createChildFrame(frameRequest, ownerElement);
645}
646
647PassRefPtr<Widget> FrameLoaderClientImpl::createPlugin(
648    const IntSize& size, // FIXME: how do we use this?
649    HTMLPlugInElement* element,
650    const KURL& url,
651    const Vector<String>& paramNames,
652    const Vector<String>& paramValues,
653    const String& mimeType,
654    bool loadManually)
655{
656    if (!m_webFrame->client())
657        return 0;
658
659    WebPluginParams params;
660    params.url = url;
661    params.mimeType = mimeType;
662    params.attributeNames = paramNames;
663    params.attributeValues = paramValues;
664    params.loadManually = loadManually;
665
666    WebPlugin* webPlugin = m_webFrame->client()->createPlugin(m_webFrame, params);
667    if (!webPlugin)
668        return 0;
669
670    // The container takes ownership of the WebPlugin.
671    RefPtr<WebPluginContainerImpl> container =
672        WebPluginContainerImpl::create(element, webPlugin);
673
674    if (!webPlugin->initialize(container.get()))
675        return 0;
676
677    // The element might have been removed during plugin initialization!
678    if (!element->renderer())
679        return 0;
680
681    return container;
682}
683
684PassRefPtr<Widget> FrameLoaderClientImpl::createJavaAppletWidget(
685    const IntSize& size,
686    HTMLAppletElement* element,
687    const KURL& /* baseURL */,
688    const Vector<String>& paramNames,
689    const Vector<String>& paramValues)
690{
691    return createPlugin(size, element, KURL(), paramNames, paramValues,
692        "application/x-java-applet", false);
693}
694
695ObjectContentType FrameLoaderClientImpl::objectContentType(
696    const KURL& url,
697    const String& explicitMimeType,
698    bool shouldPreferPlugInsForImages)
699{
700    // This code is based on Apple's implementation from
701    // WebCoreSupport/WebFrameBridge.mm.
702
703    String mimeType = explicitMimeType;
704    if (mimeType.isEmpty()) {
705        // Try to guess the MIME type based off the extension.
706        String filename = url.lastPathComponent();
707        int extensionPos = filename.reverseFind('.');
708        if (extensionPos >= 0) {
709            String extension = filename.substring(extensionPos + 1);
710            mimeType = MIMETypeRegistry::getMIMETypeForExtension(extension);
711            if (mimeType.isEmpty()) {
712                // If there's no mimetype registered for the extension, check to see
713                // if a plugin can handle the extension.
714                mimeType = getPluginMimeTypeFromExtension(extension);
715            }
716        }
717
718        if (mimeType.isEmpty())
719            return ObjectContentFrame;
720    }
721
722    // If Chrome is started with the --disable-plugins switch, pluginData is 0.
723    PluginData* pluginData = m_webFrame->frame()->page()->pluginData();
724    bool plugInSupportsMIMEType = pluginData && pluginData->supportsMimeType(mimeType);
725
726    if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType))
727        return shouldPreferPlugInsForImages && plugInSupportsMIMEType ? ObjectContentNetscapePlugin : ObjectContentImage;
728
729    if (plugInSupportsMIMEType)
730        return ObjectContentNetscapePlugin;
731
732    if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType))
733        return ObjectContentFrame;
734
735    return ObjectContentNone;
736}
737
738PassOwnPtr<WebPluginLoadObserver> FrameLoaderClientImpl::pluginLoadObserver()
739{
740    WebDataSourceImpl* ds = WebDataSourceImpl::fromDocumentLoader(
741        m_webFrame->frame()->loader()->activeDocumentLoader());
742    if (!ds) {
743        // We can arrive here if a popstate event handler detaches this frame.
744        // FIXME: Remove this code once http://webkit.org/b/36202 is fixed.
745        ASSERT(!m_webFrame->frame()->page());
746        return nullptr;
747    }
748    return ds->releasePluginLoadObserver();
749}
750
751WebCookieJar* FrameLoaderClientImpl::cookieJar() const
752{
753    if (!m_webFrame->client())
754        return 0;
755    return m_webFrame->client()->cookieJar(m_webFrame);
756}
757
758bool FrameLoaderClientImpl::willCheckAndDispatchMessageEvent(
759    SecurityOrigin* target, MessageEvent* event) const
760{
761    if (!m_webFrame->client())
762        return false;
763
764    WebFrame* source = 0;
765    if (event && event->source() && event->source()->document())
766        source = WebFrameImpl::fromFrame(event->source()->document()->frame());
767    return m_webFrame->client()->willCheckAndDispatchMessageEvent(
768        source, m_webFrame, WebSecurityOrigin(target), WebDOMMessageEvent(event));
769}
770
771void FrameLoaderClientImpl::didChangeName(const String& name)
772{
773    if (!m_webFrame->client())
774        return;
775    m_webFrame->client()->didChangeName(m_webFrame, name);
776}
777
778void FrameLoaderClientImpl::dispatchWillOpenSocketStream(SocketStreamHandle* handle)
779{
780    m_webFrame->client()->willOpenSocketStream(SocketStreamHandleInternal::toWebSocketStreamHandle(handle));
781}
782
783void FrameLoaderClientImpl::dispatchWillStartUsingPeerConnectionHandler(RTCPeerConnectionHandler* handler)
784{
785    m_webFrame->client()->willStartUsingPeerConnectionHandler(webFrame(), RTCPeerConnectionHandler::toWebRTCPeerConnectionHandler(handler));
786}
787
788void FrameLoaderClientImpl::didRequestAutocomplete(PassRefPtr<FormState> formState)
789{
790    if (m_webFrame->viewImpl() && m_webFrame->viewImpl()->autofillClient())
791        m_webFrame->viewImpl()->autofillClient()->didRequestAutocomplete(m_webFrame, WebFormElement(formState->form()));
792}
793
794bool FrameLoaderClientImpl::allowWebGL(bool enabledPerSettings)
795{
796    if (m_webFrame->client())
797        return m_webFrame->client()->allowWebGL(m_webFrame, enabledPerSettings);
798
799    return enabledPerSettings;
800}
801
802void FrameLoaderClientImpl::didLoseWebGLContext(int arbRobustnessContextLostReason)
803{
804    if (m_webFrame->client())
805        m_webFrame->client()->didLoseWebGLContext(m_webFrame, arbRobustnessContextLostReason);
806}
807
808void FrameLoaderClientImpl::dispatchWillInsertBody()
809{
810    if (m_webFrame->client())
811        m_webFrame->client()->willInsertBody(m_webFrame);
812}
813
814} // namespace WebKit
815