1/*
2 * Copyright (C) 2007 Apple Inc.  All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "WebKitDLL.h"
28#include "DefaultPolicyDelegate.h"
29
30#include "WebKit.h"
31
32#pragma warning(push, 0)
33#include <WebCore/PlatformString.h>
34#pragma warning(pop)
35
36using namespace WebCore;
37
38// FIXME: move this enum to a separate header file when other code begins to use it.
39typedef enum WebExtraNavigationType {
40    WebNavigationTypePlugInRequest = WebNavigationTypeOther + 1
41} WebExtraNavigationType;
42
43// DefaultPolicyDelegate ----------------------------------------------------------------
44
45DefaultPolicyDelegate::DefaultPolicyDelegate()
46    : m_refCount(0)
47{
48    gClassCount++;
49    gClassNameCount.add("DefaultPolicyDelegate");
50}
51
52DefaultPolicyDelegate::~DefaultPolicyDelegate()
53{
54    gClassCount--;
55    gClassNameCount.remove("DefaultPolicyDelegate");
56}
57
58DefaultPolicyDelegate* DefaultPolicyDelegate::sharedInstance()
59{
60    static COMPtr<DefaultPolicyDelegate> shared;
61    if (!shared)
62        shared.adoptRef(DefaultPolicyDelegate::createInstance());
63    return shared.get();
64}
65
66DefaultPolicyDelegate* DefaultPolicyDelegate::createInstance()
67{
68    DefaultPolicyDelegate* instance = new DefaultPolicyDelegate();
69    instance->AddRef();
70    return instance;
71}
72
73// IUnknown -------------------------------------------------------------------
74
75HRESULT STDMETHODCALLTYPE DefaultPolicyDelegate::QueryInterface(REFIID riid, void** ppvObject)
76{
77    *ppvObject = 0;
78    if (IsEqualGUID(riid, IID_IUnknown))
79        *ppvObject = static_cast<IUnknown*>(this);
80    else if (IsEqualGUID(riid, IID_IWebPolicyDelegate))
81        *ppvObject = static_cast<IWebPolicyDelegate*>(this);
82    else
83        return E_NOINTERFACE;
84
85    AddRef();
86    return S_OK;
87}
88
89ULONG STDMETHODCALLTYPE DefaultPolicyDelegate::AddRef()
90{
91    return ++m_refCount;
92}
93
94ULONG STDMETHODCALLTYPE DefaultPolicyDelegate::Release()
95{
96    ULONG newRef = --m_refCount;
97    if (!newRef)
98        delete(this);
99
100    return newRef;
101}
102
103HRESULT STDMETHODCALLTYPE DefaultPolicyDelegate::decidePolicyForNavigationAction(
104    /*[in]*/ IWebView* webView,
105    /*[in]*/ IPropertyBag* actionInformation,
106    /*[in]*/ IWebURLRequest* request,
107    /*[in]*/ IWebFrame* /*frame*/,
108    /*[in]*/ IWebPolicyDecisionListener* listener)
109{
110    int navType = 0;
111    VARIANT var;
112    if (SUCCEEDED(actionInformation->Read(WebActionNavigationTypeKey, &var, 0))) {
113        V_VT(&var) = VT_I4;
114        navType = V_I4(&var);
115    }
116    COMPtr<IWebViewPrivate> wvPrivate(Query, webView);
117    if (wvPrivate) {
118        BOOL canHandleRequest = FALSE;
119        if (SUCCEEDED(wvPrivate->canHandleRequest(request, &canHandleRequest)) && canHandleRequest)
120            listener->use();
121        else if (navType == WebNavigationTypePlugInRequest)
122            listener->use();
123        else {
124            BSTR url;
125            // A file URL shouldn't fall through to here, but if it did,
126            // it would be a security risk to open it.
127            if (SUCCEEDED(request->URL(&url)) && !String(url, SysStringLen(url)).startsWith("file:")) {
128                // FIXME: Open the URL not by means of a webframe, but by handing it over to the system and letting it determine how to open that particular URL scheme.  See documentation for [NSWorkspace openURL]
129                ;
130            }
131            listener->ignore();
132            SysFreeString(url);
133        }
134    }
135    return S_OK;
136}
137
138HRESULT STDMETHODCALLTYPE DefaultPolicyDelegate::decidePolicyForNewWindowAction(
139    /*[in]*/ IWebView* /*webView*/,
140    /*[in]*/ IPropertyBag* /*actionInformation*/,
141    /*[in]*/ IWebURLRequest* /*request*/,
142    /*[in]*/ BSTR /*frameName*/,
143    /*[in]*/ IWebPolicyDecisionListener* listener)
144{
145    listener->use();
146    return S_OK;
147}
148
149HRESULT STDMETHODCALLTYPE DefaultPolicyDelegate::decidePolicyForMIMEType(
150    /*[in]*/ IWebView* webView,
151    /*[in]*/ BSTR type,
152    /*[in]*/ IWebURLRequest* request,
153    /*[in]*/ IWebFrame* /*frame*/,
154    /*[in]*/ IWebPolicyDecisionListener* listener)
155{
156    BOOL canShowMIMEType;
157    if (FAILED(webView->canShowMIMEType(type, &canShowMIMEType)))
158        canShowMIMEType = FALSE;
159
160    BSTR url;
161    request->URL(&url);
162
163    if (String(url, SysStringLen(url)).startsWith("file:")) {
164        BOOL isDirectory = FALSE;
165        WIN32_FILE_ATTRIBUTE_DATA attrs;
166        if (GetFileAttributesEx(url, GetFileExInfoStandard, &attrs))
167            isDirectory = !!(attrs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
168
169        if (isDirectory)
170            listener->ignore();
171        else if(canShowMIMEType)
172            listener->use();
173        else
174            listener->ignore();
175    } else if (canShowMIMEType)
176        listener->use();
177    else
178        listener->ignore();
179    SysFreeString(url);
180    return S_OK;
181}
182
183HRESULT STDMETHODCALLTYPE DefaultPolicyDelegate::unableToImplementPolicyWithError(
184    /*[in]*/ IWebView* /*webView*/,
185    /*[in]*/ IWebError* error,
186    /*[in]*/ IWebFrame* frame)
187{
188    BSTR errorStr;
189    error->localizedDescription(&errorStr);
190
191    BSTR frameName;
192    frame->name(&frameName);
193
194    LOG_ERROR("called unableToImplementPolicyWithError:%S inFrame:%S", errorStr ? errorStr : TEXT(""), frameName ? frameName : TEXT(""));
195    SysFreeString(errorStr);
196    SysFreeString(frameName);
197
198    return S_OK;
199}
200