WebCore:
[WebKit-https.git] / WebKitTools / DumpRenderTree / win / ResourceLoadDelegate.cpp
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  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer. 
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution. 
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission. 
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "config.h"
30 #include "ResourceLoadDelegate.h"
31
32 #include "DumpRenderTree.h"
33 #include "LayoutTestController.h"
34 #include <wtf/HashMap.h>
35 #include <wtf/Vector.h>
36 #include <sstream>
37
38 using std::wstring;
39 using std::wiostream;
40
41 static inline wstring wstringFromBSTR(BSTR str)
42 {
43     return wstring(str, ::SysStringLen(str));
44 }
45
46 wstring wstringFromInt(int i)
47 {
48     std::wostringstream ss;
49     ss << i;
50     return ss.str();
51 }
52
53 typedef HashMap<unsigned long, wstring> IdentifierMap;
54
55 IdentifierMap& urlMap()
56 {
57     static IdentifierMap urlMap;
58
59     return urlMap;
60 }
61
62 static wstring descriptionSuitableForTestResult(unsigned long identifier)
63 {
64     IdentifierMap::iterator it = urlMap().find(identifier);
65     
66     if (it == urlMap().end())
67         return L"<unknown>";
68
69     return urlSuitableForTestResult(it->second);
70 }
71
72 static wstring descriptionSuitableForTestResult(IWebURLRequest* request)
73 {
74     if (!request)
75         return L"(null)";
76
77     BSTR urlBSTR;
78     if (FAILED(request->URL(&urlBSTR)))
79         return wstring();
80     
81     wstring url = urlSuitableForTestResult(wstringFromBSTR(urlBSTR));
82     ::SysFreeString(urlBSTR);
83     
84     BSTR mainDocumentURLBSTR;
85     if (FAILED(request->mainDocumentURL(&mainDocumentURLBSTR)))
86         return wstring();
87     
88     wstring mainDocumentURL = urlSuitableForTestResult(wstringFromBSTR(mainDocumentURLBSTR));
89     ::SysFreeString(mainDocumentURLBSTR);
90
91     return L"<NSURLRequest URL " + url + L", main document URL " + mainDocumentURL + L">";
92 }
93
94 static wstring descriptionSuitableForTestResult(IWebURLResponse* response)
95 {
96     if (!response)
97         return L"(null)";
98
99     BSTR urlBSTR;
100     if (FAILED(response->URL(&urlBSTR)))
101         return wstring();
102     
103     wstring url = urlSuitableForTestResult(wstringFromBSTR(urlBSTR));
104     ::SysFreeString(urlBSTR);
105
106     return L"<NSURLResponse " + url + L">";
107 }
108
109 static wstring descriptionSuitableForTestResult(IWebError* error, unsigned long identifier)
110 {
111     wstring result = L"<NSError ";
112
113     BSTR domainSTR;
114     if (FAILED(error->domain(&domainSTR)))
115         return wstring();
116
117     wstring domain = wstringFromBSTR(domainSTR);
118     ::SysFreeString(domainSTR);
119
120     int code;
121     if (FAILED(error->code(&code)))
122         return wstring();
123
124     if (domain == L"CFURLErrorDomain") {
125         domain = L"NSURLErrorDomain";
126
127         // Convert kCFURLErrorUnknown to NSURLErrorUnknown
128         if (code == -998)
129             code = -1;
130     } else if (domain == L"kCFErrorDomainWinSock") {
131         domain = L"NSURLErrorDomain";
132
133         // Convert the winsock error code to an NSURLError code.
134         if (code == WSAEADDRNOTAVAIL)
135             code = -1004; // NSURLErrorCannotConnectToHose;
136     }
137
138     result += L"domain " + domain;
139     result += L", code " + wstringFromInt(code);
140
141     BSTR failingURLSTR;
142     if (FAILED(error->failingURL(&failingURLSTR)))
143         return wstring();
144
145     wstring failingURL;
146     
147     // If the error doesn't have a failing URL, we fake one by using the URL the resource had 
148     // at creation time. This seems to work fine for now.
149     // See <rdar://problem/5064234> CFErrors should have failingURL key.
150     if (failingURLSTR)
151         failingURL = wstringFromBSTR(failingURLSTR);
152     else
153         failingURL = descriptionSuitableForTestResult(identifier);
154
155     ::SysFreeString(failingURLSTR);
156
157     result += L", failing URL \"" + urlSuitableForTestResult(failingURL) + L"\">";
158
159     return result;
160 }
161
162 ResourceLoadDelegate::ResourceLoadDelegate()
163     : m_refCount(1)
164 {
165 }
166
167 ResourceLoadDelegate::~ResourceLoadDelegate()
168 {
169 }
170
171 HRESULT STDMETHODCALLTYPE ResourceLoadDelegate::QueryInterface(REFIID riid, void** ppvObject)
172 {
173     *ppvObject = 0;
174     if (IsEqualGUID(riid, IID_IUnknown))
175         *ppvObject = static_cast<IWebResourceLoadDelegate*>(this);
176     else if (IsEqualGUID(riid, IID_IWebResourceLoadDelegate))
177         *ppvObject = static_cast<IWebResourceLoadDelegate*>(this);
178     else
179         return E_NOINTERFACE;
180
181     AddRef();
182     return S_OK;
183 }
184
185 ULONG STDMETHODCALLTYPE ResourceLoadDelegate::AddRef(void)
186 {
187     return ++m_refCount;
188 }
189
190 ULONG STDMETHODCALLTYPE ResourceLoadDelegate::Release(void)
191 {
192     ULONG newRef = --m_refCount;
193     if (!newRef)
194         delete(this);
195
196     return newRef;
197 }
198
199 HRESULT STDMETHODCALLTYPE ResourceLoadDelegate::identifierForInitialRequest( 
200     /* [in] */ IWebView* webView,
201     /* [in] */ IWebURLRequest* request,
202     /* [in] */ IWebDataSource* dataSource,
203     /* [in] */ unsigned long identifier)
204
205     if (!done && gLayoutTestController->dumpResourceLoadCallbacks()) {
206         BSTR urlStr;
207         if (FAILED(request->URL(&urlStr)))
208             return E_FAIL;
209
210         urlMap().set(identifier, wstringFromBSTR(urlStr));
211     }
212
213     return S_OK;
214 }
215
216 HRESULT STDMETHODCALLTYPE ResourceLoadDelegate::willSendRequest( 
217     /* [in] */ IWebView* webView,
218     /* [in] */ unsigned long identifier,
219     /* [in] */ IWebURLRequest* request,
220     /* [in] */ IWebURLResponse* redirectResponse,
221     /* [in] */ IWebDataSource* dataSource,
222     /* [retval][out] */ IWebURLRequest **newRequest)
223 {
224     if (!done && gLayoutTestController->dumpResourceLoadCallbacks()) {
225         printf("%S - willSendRequest %S redirectResponse %S\n", 
226             descriptionSuitableForTestResult(identifier).c_str(),
227             descriptionSuitableForTestResult(request).c_str(),
228             descriptionSuitableForTestResult(redirectResponse).c_str());
229     }
230
231     request->AddRef();
232     *newRequest = request;
233     return S_OK;
234 }
235
236 HRESULT STDMETHODCALLTYPE ResourceLoadDelegate::didFinishLoadingFromDataSource( 
237     /* [in] */ IWebView* webView,
238     /* [in] */ unsigned long identifier,
239     /* [in] */ IWebDataSource* dataSource)
240 {
241     if (!done && gLayoutTestController->dumpResourceLoadCallbacks()) {
242         printf("%S - didFinishLoading\n",
243             descriptionSuitableForTestResult(identifier).c_str()),
244        urlMap().remove(identifier);
245     }
246
247    return S_OK;
248 }
249         
250 HRESULT STDMETHODCALLTYPE ResourceLoadDelegate::didFailLoadingWithError( 
251     /* [in] */ IWebView* webView,
252     /* [in] */ unsigned long identifier,
253     /* [in] */ IWebError* error,
254     /* [in] */ IWebDataSource* dataSource)
255 {
256     if (!done && gLayoutTestController->dumpResourceLoadCallbacks()) {
257         printf("%S - didFailLoadingWithError: %S\n", 
258             descriptionSuitableForTestResult(identifier).c_str(),
259             descriptionSuitableForTestResult(error, identifier).c_str());
260         urlMap().remove(identifier);
261     }
262
263     return S_OK;
264 }