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