WebKit/win/WebURLResponse.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2006, 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 "WebURLResponse.h"
       
    28 
       
    29 #include "WebKitDLL.h"
       
    30 #include "WebKit.h"
       
    31 
       
    32 #include "COMPropertyBag.h"
       
    33 #include "MarshallingHelpers.h"
       
    34 #include "WebLocalizableStrings.h"
       
    35 
       
    36 #if USE(CFNETWORK)
       
    37 #include <WebKitSystemInterface/WebKitSystemInterface.h>
       
    38 #endif
       
    39 
       
    40 #include <wtf/platform.h>
       
    41 #pragma warning( push, 0 )
       
    42 #include <WebCore/BString.h>
       
    43 #include <WebCore/KURL.h>
       
    44 #include <WebCore/ResourceHandle.h>
       
    45 #pragma warning( pop )
       
    46 #include <shlobj.h>
       
    47 #include <shlwapi.h>
       
    48 #include <tchar.h>
       
    49 
       
    50 using namespace WebCore;
       
    51 
       
    52 static LPCTSTR CFHTTPMessageCopyLocalizedShortDescriptionForStatusCode(CFIndex statusCode)
       
    53 {
       
    54     LPCTSTR result = 0;
       
    55     if (statusCode < 100 || statusCode >= 600)
       
    56         result = LPCTSTR_UI_STRING("server error", "HTTP result code string");
       
    57     else if (statusCode >= 100 && statusCode <= 199) {
       
    58         switch (statusCode) {
       
    59             case 100:
       
    60                 result = LPCTSTR_UI_STRING("continue", "HTTP result code string");
       
    61                 break;
       
    62             case 101:
       
    63                 result = LPCTSTR_UI_STRING("switching protocols", "HTTP result code string");
       
    64                 break;
       
    65             default:
       
    66                 result = LPCTSTR_UI_STRING("informational", "HTTP result code string");
       
    67                 break;
       
    68         }
       
    69     } else if (statusCode >= 200 && statusCode <= 299) {
       
    70         switch (statusCode) {
       
    71             case 200:
       
    72                 result = LPCTSTR_UI_STRING("no error", "HTTP result code string");
       
    73                 break;
       
    74             case 201:
       
    75                 result = LPCTSTR_UI_STRING("created", "HTTP result code string");
       
    76                 break;
       
    77             case 202:
       
    78                 result = LPCTSTR_UI_STRING("accepted", "HTTP result code string");
       
    79                 break;
       
    80             case 203:
       
    81                 result = LPCTSTR_UI_STRING("non-authoritative information", "HTTP result code string");
       
    82                 break;
       
    83             case 204:
       
    84                 result = LPCTSTR_UI_STRING("no content", "HTTP result code string");
       
    85                 break;
       
    86             case 205:
       
    87                 result = LPCTSTR_UI_STRING("reset content", "HTTP result code string");
       
    88                 break;
       
    89             case 206:
       
    90                 result = LPCTSTR_UI_STRING("partial content", "HTTP result code string");
       
    91                 break;
       
    92             default:
       
    93                 result = LPCTSTR_UI_STRING("success", "HTTP result code string");
       
    94                 break;
       
    95         } 
       
    96     } else if (statusCode >= 300 && statusCode <= 399) {
       
    97         switch (statusCode) {
       
    98             case 300:
       
    99                 result = LPCTSTR_UI_STRING("multiple choices", "HTTP result code string");
       
   100                 break;
       
   101             case 301:
       
   102                 result = LPCTSTR_UI_STRING("moved permanently", "HTTP result code string");
       
   103                 break;
       
   104             case 302:
       
   105                 result = LPCTSTR_UI_STRING("found", "HTTP result code string");
       
   106                 break;
       
   107             case 303:
       
   108                 result = LPCTSTR_UI_STRING("see other", "HTTP result code string");
       
   109                 break;
       
   110             case 304:
       
   111                 result = LPCTSTR_UI_STRING("not modified", "HTTP result code string");
       
   112                 break;
       
   113             case 305:
       
   114                 result = LPCTSTR_UI_STRING("needs proxy", "HTTP result code string");
       
   115                 break;
       
   116             case 307:
       
   117                 result = LPCTSTR_UI_STRING("temporarily redirected", "HTTP result code string");
       
   118                 break;
       
   119             case 306:   // 306 status code unused in HTTP
       
   120             default:
       
   121                 result = LPCTSTR_UI_STRING("redirected", "HTTP result code string");
       
   122                 break;
       
   123         }
       
   124     } else if (statusCode >= 400 && statusCode <= 499) {
       
   125         switch (statusCode) {
       
   126             case 400:
       
   127                 result = LPCTSTR_UI_STRING("bad request", "HTTP result code string");
       
   128                 break;
       
   129             case 401:
       
   130                 result = LPCTSTR_UI_STRING("unauthorized", "HTTP result code string");
       
   131                 break;
       
   132             case 402:
       
   133                 result = LPCTSTR_UI_STRING("payment required", "HTTP result code string");
       
   134                 break;
       
   135             case 403:
       
   136                 result = LPCTSTR_UI_STRING("forbidden", "HTTP result code string");
       
   137                 break;
       
   138             case 404:
       
   139                 result = LPCTSTR_UI_STRING("not found", "HTTP result code string");
       
   140                 break;
       
   141             case 405:
       
   142                 result = LPCTSTR_UI_STRING("method not allowed", "HTTP result code string");
       
   143                 break;
       
   144             case 406:
       
   145                 result = LPCTSTR_UI_STRING("unacceptable", "HTTP result code string");
       
   146                 break;
       
   147             case 407:
       
   148                 result = LPCTSTR_UI_STRING("proxy authentication required", "HTTP result code string");
       
   149                 break;
       
   150             case 408:
       
   151                 result = LPCTSTR_UI_STRING("request timed out", "HTTP result code string");
       
   152                 break;
       
   153             case 409:
       
   154                 result = LPCTSTR_UI_STRING("conflict", "HTTP result code string");
       
   155                 break;
       
   156             case 410:
       
   157                 result = LPCTSTR_UI_STRING("no longer exists", "HTTP result code string");
       
   158                 break;
       
   159             case 411:
       
   160                 result = LPCTSTR_UI_STRING("length required", "HTTP result code string");
       
   161                 break;
       
   162             case 412:
       
   163                 result = LPCTSTR_UI_STRING("precondition failed", "HTTP result code string");
       
   164                 break;
       
   165             case 413:
       
   166                 result = LPCTSTR_UI_STRING("request too large", "HTTP result code string");
       
   167                 break;
       
   168             case 414:
       
   169                 result = LPCTSTR_UI_STRING("requested URL too long", "HTTP result code string");
       
   170                 break;
       
   171             case 415:
       
   172                 result = LPCTSTR_UI_STRING("unsupported media type", "HTTP result code string");
       
   173                 break;
       
   174             case 416:
       
   175                 result = LPCTSTR_UI_STRING("requested range not satisfiable", "HTTP result code string");
       
   176                 break;
       
   177             case 417:
       
   178                 result = LPCTSTR_UI_STRING("expectation failed", "HTTP result code string");
       
   179                 break;
       
   180             default:
       
   181                 result = LPCTSTR_UI_STRING("client error", "HTTP result code string");
       
   182                 break;
       
   183         }
       
   184     } else if (statusCode >= 500 && statusCode <= 599) {
       
   185         switch (statusCode) {
       
   186             case 500:
       
   187                 result = LPCTSTR_UI_STRING("internal server error", "HTTP result code string");
       
   188                 break;
       
   189             case 501:
       
   190                 result = LPCTSTR_UI_STRING("unimplemented", "HTTP result code string");
       
   191                 break;
       
   192             case 502:
       
   193                 result = LPCTSTR_UI_STRING("bad gateway", "HTTP result code string");
       
   194                 break;
       
   195             case 503:
       
   196                 result = LPCTSTR_UI_STRING("service unavailable", "HTTP result code string");
       
   197                 break;
       
   198             case 504:
       
   199                 result = LPCTSTR_UI_STRING("gateway timed out", "HTTP result code string");
       
   200                 break;
       
   201             case 505:
       
   202                 result = LPCTSTR_UI_STRING("unsupported version", "HTTP result code string");
       
   203                 break;
       
   204             default:
       
   205                 result = LPCTSTR_UI_STRING("server error", "HTTP result code string");
       
   206                 break;
       
   207         }
       
   208     }
       
   209     return result;
       
   210 }
       
   211 
       
   212 // IWebURLResponse ----------------------------------------------------------------
       
   213 
       
   214 WebURLResponse::WebURLResponse()
       
   215     :m_refCount(0)
       
   216 {
       
   217     gClassCount++;
       
   218     gClassNameCount.add("WebURLResponse");
       
   219 }
       
   220 
       
   221 WebURLResponse::~WebURLResponse()
       
   222 {
       
   223     gClassCount--;
       
   224     gClassNameCount.remove("WebURLResponse");
       
   225 }
       
   226 
       
   227 WebURLResponse* WebURLResponse::createInstance()
       
   228 {
       
   229     WebURLResponse* instance = new WebURLResponse();
       
   230     // fake an http response - so it has the IWebHTTPURLResponse interface
       
   231     instance->m_response = ResourceResponse(KURL(ParsedURLString, "http://"), String(), 0, String(), String());
       
   232     instance->AddRef();
       
   233     return instance;
       
   234 }
       
   235 
       
   236 WebURLResponse* WebURLResponse::createInstance(const ResourceResponse& response)
       
   237 {
       
   238     if (response.isNull())
       
   239         return 0;
       
   240 
       
   241     WebURLResponse* instance = new WebURLResponse();
       
   242     instance->AddRef();
       
   243     instance->m_response = response;
       
   244 
       
   245     return instance;
       
   246 }
       
   247 
       
   248 // IUnknown -------------------------------------------------------------------
       
   249 
       
   250 HRESULT STDMETHODCALLTYPE WebURLResponse::QueryInterface(REFIID riid, void** ppvObject)
       
   251 {
       
   252     *ppvObject = 0;
       
   253     if (IsEqualGUID(riid, IID_IUnknown))
       
   254         *ppvObject = static_cast<IWebURLResponse*>(this);
       
   255     else if (IsEqualGUID(riid, __uuidof(this)))
       
   256         *ppvObject = this;
       
   257     else if (IsEqualGUID(riid, IID_IWebURLResponse))
       
   258         *ppvObject = static_cast<IWebURLResponse*>(this);
       
   259     else if (IsEqualGUID(riid, IID_IWebURLResponsePrivate))
       
   260         *ppvObject = static_cast<IWebURLResponsePrivate*>(this);
       
   261     else if (m_response.isHTTP() && IsEqualGUID(riid, IID_IWebHTTPURLResponse))
       
   262         *ppvObject = static_cast<IWebHTTPURLResponse*>(this);
       
   263     else
       
   264         return E_NOINTERFACE;
       
   265 
       
   266     AddRef();
       
   267     return S_OK;
       
   268 }
       
   269 
       
   270 ULONG STDMETHODCALLTYPE WebURLResponse::AddRef(void)
       
   271 {
       
   272     return ++m_refCount;
       
   273 }
       
   274 
       
   275 ULONG STDMETHODCALLTYPE WebURLResponse::Release(void)
       
   276 {
       
   277     ULONG newRef = --m_refCount;
       
   278     if (!newRef)
       
   279         delete(this);
       
   280 
       
   281     return newRef;
       
   282 }
       
   283 
       
   284 // IWebURLResponse --------------------------------------------------------------------
       
   285 
       
   286 HRESULT STDMETHODCALLTYPE WebURLResponse::expectedContentLength( 
       
   287     /* [retval][out] */ long long* result)
       
   288 {
       
   289     *result = m_response.expectedContentLength();
       
   290     return S_OK;
       
   291 }
       
   292 
       
   293 HRESULT STDMETHODCALLTYPE WebURLResponse::initWithURL( 
       
   294     /* [in] */ BSTR url,
       
   295     /* [in] */ BSTR mimeType,
       
   296     /* [in] */ int expectedContentLength,
       
   297     /* [in] */ BSTR textEncodingName)
       
   298 {
       
   299     m_response = ResourceResponse(MarshallingHelpers::BSTRToKURL(url), String(mimeType), expectedContentLength, String(textEncodingName), String());
       
   300     return S_OK;
       
   301 }
       
   302 
       
   303 HRESULT STDMETHODCALLTYPE WebURLResponse::MIMEType( 
       
   304     /* [retval][out] */ BSTR* result)
       
   305 {
       
   306     BString mimeType(m_response.mimeType());
       
   307     *result = mimeType.release();
       
   308     if (!m_response.mimeType().isNull() && !*result)
       
   309         return E_OUTOFMEMORY;
       
   310 
       
   311     return S_OK;
       
   312 }
       
   313 
       
   314 HRESULT STDMETHODCALLTYPE WebURLResponse::suggestedFilename( 
       
   315     /* [retval][out] */ BSTR* result)
       
   316 {
       
   317     if (!result) {
       
   318         ASSERT_NOT_REACHED();
       
   319         return E_POINTER;
       
   320     }
       
   321 
       
   322     *result = 0;
       
   323 
       
   324     if (m_response.url().isEmpty())
       
   325         return E_FAIL;
       
   326 
       
   327     *result = BString(m_response.suggestedFilename()).release();
       
   328     return S_OK;
       
   329 }
       
   330 
       
   331 HRESULT STDMETHODCALLTYPE WebURLResponse::textEncodingName( 
       
   332     /* [retval][out] */ BSTR* result)
       
   333 {
       
   334     if (!result)
       
   335         return E_INVALIDARG;
       
   336 
       
   337     BString textEncodingName(m_response.textEncodingName());
       
   338     *result = textEncodingName.release();
       
   339     if (!m_response.textEncodingName().isNull() && !*result)
       
   340         return E_OUTOFMEMORY;
       
   341 
       
   342     return S_OK;
       
   343 }
       
   344 
       
   345 HRESULT STDMETHODCALLTYPE WebURLResponse::URL( 
       
   346     /* [retval][out] */ BSTR* result)
       
   347 {
       
   348     if (!result)
       
   349         return E_INVALIDARG;
       
   350 
       
   351     BString url(m_response.url().string());
       
   352     *result = url.release();
       
   353     if (!m_response.url().isEmpty() && !*result)
       
   354         return E_OUTOFMEMORY;
       
   355 
       
   356     return S_OK;
       
   357 }
       
   358 
       
   359 // IWebHTTPURLResponse --------------------------------------------------------
       
   360 
       
   361 HRESULT STDMETHODCALLTYPE WebURLResponse::allHeaderFields( 
       
   362     /* [retval][out] */ IPropertyBag** headerFields)
       
   363 {
       
   364     ASSERT(m_response.isHTTP());
       
   365 
       
   366     *headerFields = COMPropertyBag<String, AtomicString, CaseFoldingHash>::createInstance(m_response.httpHeaderFields());
       
   367     return S_OK;
       
   368 }
       
   369 
       
   370 HRESULT STDMETHODCALLTYPE WebURLResponse::localizedStringForStatusCode( 
       
   371     /* [in] */ int statusCode,
       
   372     /* [retval][out] */ BSTR* statusString)
       
   373 {
       
   374     ASSERT(m_response.isHTTP());
       
   375     if (statusString)
       
   376         *statusString = 0;
       
   377     LPCTSTR statusText = CFHTTPMessageCopyLocalizedShortDescriptionForStatusCode(statusCode);
       
   378     if (!statusText)
       
   379         return E_FAIL;
       
   380     if (statusString)
       
   381         *statusString = SysAllocString(statusText);
       
   382     return S_OK;
       
   383 }
       
   384 
       
   385 HRESULT STDMETHODCALLTYPE WebURLResponse::statusCode( 
       
   386     /* [retval][out] */ int* statusCode)
       
   387 {
       
   388     ASSERT(m_response.isHTTP());
       
   389     if (statusCode)
       
   390         *statusCode = m_response.httpStatusCode();
       
   391     return S_OK;
       
   392 }
       
   393 
       
   394 HRESULT STDMETHODCALLTYPE WebURLResponse::isAttachment( 
       
   395     /* [retval][out] */ BOOL *attachment)
       
   396 {
       
   397     *attachment = m_response.isAttachment();
       
   398     return S_OK;
       
   399 }
       
   400 
       
   401 
       
   402 HRESULT STDMETHODCALLTYPE WebURLResponse::sslPeerCertificate( 
       
   403     /* [retval][out] */ OLE_HANDLE* result)
       
   404 {
       
   405     if (!result)
       
   406         return E_POINTER;
       
   407     *result = 0;
       
   408 
       
   409 #if USE(CFNETWORK)
       
   410     CFDictionaryRef dict = certificateDictionary();
       
   411     if (!dict)
       
   412         return E_FAIL;
       
   413     void* data = wkGetSSLPeerCertificateData(dict);
       
   414     if (!data)
       
   415         return E_FAIL;
       
   416     *result = (OLE_HANDLE)(ULONG64)data;
       
   417 #endif
       
   418 
       
   419     return *result ? S_OK : E_FAIL;
       
   420 }
       
   421 
       
   422 // WebURLResponse -------------------------------------------------------------
       
   423 
       
   424 HRESULT WebURLResponse::suggestedFileExtension(BSTR *result)
       
   425 {
       
   426     if (!result)
       
   427         return E_POINTER;
       
   428 
       
   429     *result = 0;
       
   430 
       
   431     if (m_response.mimeType().isEmpty())
       
   432         return E_FAIL;
       
   433 
       
   434     BString mimeType(m_response.mimeType());
       
   435     HKEY key;
       
   436     LONG err = RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("MIME\\Database\\Content Type"), 0, KEY_QUERY_VALUE, &key);
       
   437     if (!err) {
       
   438         HKEY subKey;
       
   439         err = RegOpenKeyEx(key, mimeType, 0, KEY_QUERY_VALUE, &subKey);
       
   440         if (!err) {
       
   441             DWORD keyType = REG_SZ;
       
   442             TCHAR extension[MAX_PATH];
       
   443             DWORD keySize = sizeof(extension)/sizeof(extension[0]);
       
   444             err = RegQueryValueEx(subKey, TEXT("Extension"), 0, &keyType, (LPBYTE)extension, &keySize);
       
   445             if (!err && keyType != REG_SZ)
       
   446                 err = ERROR_INVALID_DATA;
       
   447             if (err) {
       
   448                 // fallback handlers
       
   449                 if (!_tcscmp(mimeType, TEXT("text/html"))) {
       
   450                     _tcscpy(extension, TEXT(".html"));
       
   451                     err = 0;
       
   452                 } else if (!_tcscmp(mimeType, TEXT("application/xhtml+xml"))) {
       
   453                     _tcscpy(extension, TEXT(".xhtml"));
       
   454                     err = 0;
       
   455                 } else if (!_tcscmp(mimeType, TEXT("image/svg+xml"))) {
       
   456                     _tcscpy(extension, TEXT(".svg"));
       
   457                     err = 0;
       
   458                 }
       
   459             }
       
   460             if (!err) {
       
   461                 *result = SysAllocString(extension);
       
   462                 if (!*result)
       
   463                     err = ERROR_OUTOFMEMORY;
       
   464             }
       
   465             RegCloseKey(subKey);
       
   466         }
       
   467         RegCloseKey(key);
       
   468     }
       
   469 
       
   470     return HRESULT_FROM_WIN32(err);
       
   471 }
       
   472 
       
   473 const ResourceResponse& WebURLResponse::resourceResponse() const
       
   474 {
       
   475     return m_response;
       
   476 }
       
   477 
       
   478 #if USE(CFNETWORK)
       
   479 CFDictionaryRef WebURLResponse::certificateDictionary() const
       
   480 {
       
   481     if (m_SSLCertificateInfo)
       
   482         return m_SSLCertificateInfo.get();
       
   483 
       
   484     CFURLResponseRef cfResponse = m_response.cfURLResponse();
       
   485     if (!cfResponse)
       
   486         return 0;
       
   487     m_SSLCertificateInfo = wkGetSSLCertificateInfo(cfResponse);
       
   488     return m_SSLCertificateInfo.get();
       
   489 }
       
   490 #endif