⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 199644 in webkit


Ignore:
Timestamp:
Apr 17, 2016, 11:58:56 AM (10 years ago)
Author:
Chris Dumez
Message:

[WK2][iOS] Do not dlopen() QuickLook in the NetworkProcess
https://bugs.webkit.org/show_bug.cgi?id=156639

Reviewed by Darin Adler.

Source/WebCore:

Do not unnecessarily dlopen() QuickLook in the NetworkProcess on iOS, as
we already dlopen() this library in the WebContent process. This patch
moves the resource response MIME type adjusting code for QuickLook from
adjustMIMETypeIfNecessary() to a new adjustMIMETypeForQuickLook() function.
adjustMIMETypeIfNecessary() is called in didReceiveResponse() in the Network
process side, for *every* resource response, even though QuickLook can only
be used to preview main resources. The new adjustMIMETypeForQuickLook()
function is called in the QuickLookHandle::createIfNecessary() factory
function, right before checking the MIME type to determine if we need to
use QuickLook, and after checking that the load is for a main resource.
In the WebKit2 case, the factory function is called from
WebResourceLoader::didReceiveResponse(), on the WebContent process side.

This patch speeds up the first page load during PLT by ~22%, because the
first load no longer triggers a dlopen() to QuickLook in the NetworkProcess.
The overall PLT score seems to be progressed by 0.9-1% as well. The change
should also be memory-positive as we no longer need to dlopen() the
QuickLook library in the NetworkProcess at all (and we would already dlopen()
it on the WebContent process side anyway). Sadly, PLUM benchmark does not
show the memory benefit because it does not measure the memory used by the
Network process.

  • platform/network/cf/SynchronousResourceHandleCFURLConnectionDelegate.cpp:

(WebCore::SynchronousResourceHandleCFURLConnectionDelegate::didReceiveResponse):
Refactor the code a bit for clarity, so that we only
ResourceHandle::setQuickLookHandle() when QuickLookHandle::createIfNecessary()
returns a non-null pointer.

  • platform/network/ios/QuickLook.h:
  • Rename the factories from create() to createIfNecessary() given that they return nullptr when it is unnecessary to create such handle (i.e. this is not a main resource loader, or it is unecessary given the response's MIME type.
  • Make shouldCreateForMIMEType() private now that this is always called inside the factory functions.
  • platform/network/ios/QuickLook.mm:

(adjustMIMETypeForQuickLook):
Extracted code for adjusting the MIME type for QuickLook from the generic
adjustMIMETypeIfNecessary() in WebCoreURLResponseIOS.mm to its own function
here.

(WebCore::QuickLookHandle::createIfNecessary):
Call adjustMIMETypeForQuickLook() before checking the MIME type.

  • platform/network/ios/WebCoreURLResponseIOS.mm:

(WebCore::adjustMIMETypeIfNecessary):
Extracted QuickLook-specific code to QuickLook.mm.

  • platform/network/mac/WebCoreResourceHandleAsDelegate.mm:

(-[WebCoreResourceHandleAsDelegate connection:didReceiveResponse:]):
Refactor the code a bit for clarity, so that we only
ResourceHandle::setQuickLookHandle() when QuickLookHandle::createIfNecessary()
returns a non-null pointer.

Source/WebKit2:

  • WebProcess/Network/WebResourceLoader.cpp:

(WebKit::WebResourceLoader::didReceiveResponse):
Move checks for main resource load and for MIME type inside of
QuickLookHandle::createIfNecessary(), for consistency with the
other QuickLookHandle factory functions.

Location:
trunk/Source
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r199643 r199644  
     12016-04-17  Chris Dumez  <cdumez@apple.com>
     2
     3        [WK2][iOS] Do not dlopen() QuickLook in the NetworkProcess
     4        https://bugs.webkit.org/show_bug.cgi?id=156639
     5
     6        Reviewed by Darin Adler.
     7
     8        Do not unnecessarily dlopen() QuickLook in the NetworkProcess on iOS, as
     9        we already dlopen() this library in the WebContent process. This patch
     10        moves the resource response MIME type adjusting code for QuickLook from
     11        adjustMIMETypeIfNecessary() to a new adjustMIMETypeForQuickLook() function.
     12        adjustMIMETypeIfNecessary() is called in didReceiveResponse() in the Network
     13        process side, for *every* resource response, even though QuickLook can only
     14        be used to preview main resources. The new adjustMIMETypeForQuickLook()
     15        function is called in the QuickLookHandle::createIfNecessary() factory
     16        function, right before checking the MIME type to determine if we need to
     17        use QuickLook, and after checking that the load is for a main resource.
     18        In the WebKit2 case, the factory function is called from
     19        WebResourceLoader::didReceiveResponse(), on the WebContent process side.
     20
     21        This patch speeds up the first page load during PLT by ~22%, because the
     22        first load no longer triggers a dlopen() to QuickLook in the NetworkProcess.
     23        The overall PLT score seems to be progressed by 0.9-1% as well. The change
     24        should also be memory-positive as we no longer need to dlopen() the
     25        QuickLook library in the NetworkProcess at all (and we would already dlopen()
     26        it on the WebContent process side anyway). Sadly, PLUM benchmark does not
     27        show the memory benefit because it does not measure the memory used by the
     28        Network process.
     29
     30        * platform/network/cf/SynchronousResourceHandleCFURLConnectionDelegate.cpp:
     31        (WebCore::SynchronousResourceHandleCFURLConnectionDelegate::didReceiveResponse):
     32        Refactor the code a bit for clarity, so that we only
     33        ResourceHandle::setQuickLookHandle() when QuickLookHandle::createIfNecessary()
     34        returns a non-null pointer.
     35
     36        * platform/network/ios/QuickLook.h:
     37        - Rename the factories from create() to createIfNecessary() given that they
     38          return nullptr when it is unnecessary to create such handle (i.e. this is not
     39          a main resource loader, or it is unecessary given the response's MIME type.
     40        - Make shouldCreateForMIMEType() private now that this is always called inside
     41          the factory functions.
     42
     43        * platform/network/ios/QuickLook.mm:
     44        (adjustMIMETypeForQuickLook):
     45        Extracted code for adjusting the MIME type for QuickLook from the generic
     46        adjustMIMETypeIfNecessary() in WebCoreURLResponseIOS.mm to its own function
     47        here.
     48
     49        (WebCore::QuickLookHandle::createIfNecessary):
     50        Call adjustMIMETypeForQuickLook() before checking the MIME type.
     51
     52        * platform/network/ios/WebCoreURLResponseIOS.mm:
     53        (WebCore::adjustMIMETypeIfNecessary):
     54        Extracted QuickLook-specific code to QuickLook.mm.
     55
     56        * platform/network/mac/WebCoreResourceHandleAsDelegate.mm:
     57        (-[WebCoreResourceHandleAsDelegate connection:didReceiveResponse:]):
     58        Refactor the code a bit for clarity, so that we only
     59        ResourceHandle::setQuickLookHandle() when QuickLookHandle::createIfNecessary()
     60        returns a non-null pointer.
     61
    1622016-04-17  Brady Eidson  <beidson@apple.com>
    263
  • trunk/Source/WebCore/platform/network/cf/SynchronousResourceHandleCFURLConnectionDelegate.cpp

    r194378 r199644  
    167167
    168168#if USE(QUICK_LOOK)
    169     m_handle->setQuickLookHandle(QuickLookHandle::create(m_handle, this, cfResponse));
    170     if (m_handle->quickLookHandle())
    171         cfResponse = m_handle->quickLookHandle()->cfResponse();
     169    if (auto quickLookHandle = QuickLookHandle::createIfNecessary(*m_handle, this, cfResponse)) {
     170        cfResponse = quickLookHandle->cfResponse();
     171        m_handle->setQuickLookHandle(WTFMove(quickLookHandle));
     172    }
    172173#endif
    173174   
  • trunk/Source/WebCore/platform/network/ios/QuickLook.h

    r194378 r199644  
    7979    WTF_MAKE_NONCOPYABLE(QuickLookHandle);
    8080public:
    81     WEBCORE_EXPORT static bool shouldCreateForMIMEType(const String&);
     81    static std::unique_ptr<QuickLookHandle> createIfNecessary(ResourceHandle&, NSURLConnection *, NSURLResponse *, id delegate);
     82#if USE(CFNETWORK)
     83    static std::unique_ptr<QuickLookHandle> createIfNecessary(ResourceHandle&, SynchronousResourceHandleCFURLConnectionDelegate*, CFURLResponseRef);
     84#endif
    8285
    83     static std::unique_ptr<QuickLookHandle> create(ResourceHandle*, NSURLConnection *, NSURLResponse *, id delegate);
    84 #if USE(CFNETWORK)
    85     static std::unique_ptr<QuickLookHandle> create(ResourceHandle*, SynchronousResourceHandleCFURLConnectionDelegate*, CFURLResponseRef);
    86 #endif
    8786    // FIXME: Use of ResourceLoader here is a platform violation.
    88     WEBCORE_EXPORT static std::unique_ptr<QuickLookHandle> create(ResourceLoader&, const ResourceResponse&);
     87    WEBCORE_EXPORT static std::unique_ptr<QuickLookHandle> createIfNecessary(ResourceLoader&, NSURLResponse *);
    8988
    9089    WEBCORE_EXPORT ~QuickLookHandle();
     
    109108
    110109private:
     110    static std::unique_ptr<QuickLookHandle> create(ResourceHandle&, NSURLConnection *, NSURLResponse *, id delegate);
    111111    QuickLookHandle(NSURL *, NSURLConnection *, NSURLResponse *, id delegate);
    112112
  • trunk/Source/WebCore/platform/network/ios/QuickLook.mm

    r197628 r199644  
    3737#import "ResourceLoader.h"
    3838#import "RuntimeApplicationChecks.h"
     39#import "SubresourceLoader.h"
    3940#import "SynchronousResourceHandleCFURLConnectionDelegate.h"
     41#import "UTIUtilities.h"
    4042#import "WebCoreResourceHandleAsDelegate.h"
     43#import "WebCoreSystemInterface.h"
    4144#import "WebCoreURLResponseIOS.h"
    4245#import <Foundation/Foundation.h>
     46#import <MobileCoreServices/MobileCoreServices.h>
    4347#import <wtf/NeverDestroyed.h>
    4448#import <wtf/StdLibExtras.h>
     
    4852
    4953#import "QuickLookSoftLink.h"
     54
     55SOFT_LINK_FRAMEWORK(MobileCoreServices)
     56
     57SOFT_LINK(MobileCoreServices, UTTypeCreatePreferredIdentifierForTag, CFStringRef, (CFStringRef inTagClass, CFStringRef inTag, CFStringRef inConformingToUTI), (inTagClass, inTag, inConformingToUTI))
     58
     59SOFT_LINK_CONSTANT(MobileCoreServices, kUTTagClassFilenameExtension, CFStringRef)
     60
     61#define kUTTagClassFilenameExtension getkUTTagClassFilenameExtension()
    5062
    5163using namespace WebCore;
     
    95107    static NSMutableDictionary *contentDictionary = [[NSMutableDictionary alloc] init];
    96108    return contentDictionary;
     109}
     110
     111// We must ensure that the MIME type is correct, so that QuickLook's web plugin is called when needed.
     112// We filter the basic MIME types so that we don't do unnecessary work in standard browsing situations.
     113static RetainPtr<CFStringRef> adjustMIMETypeForQuickLook(CFURLResponseRef cfResponse)
     114{
     115    RetainPtr<CFStringRef> mimeType = CFURLResponseGetMIMEType(cfResponse);
     116    if (!shouldUseQuickLookForMIMEType(mimeType.get()))
     117        return mimeType;
     118
     119    RetainPtr<CFStringRef> suggestedFilename = adoptCF(CFURLResponseCopySuggestedFilename(cfResponse));
     120    RetainPtr<CFStringRef> quickLookMIMEType = adoptCF((CFStringRef)QLTypeCopyBestMimeTypeForFileNameAndMimeType((NSString *)suggestedFilename.get(), (NSString *)mimeType.get()));
     121    if (!quickLookMIMEType) {
     122        auto url = CFURLResponseGetURL(cfResponse);
     123        if (![(NSURL *)url isFileURL])
     124            return mimeType;
     125        RetainPtr<CFStringRef> extension = adoptCF(CFURLCopyPathExtension(url));
     126        if (!extension)
     127            return mimeType;
     128        RetainPtr<CFStringRef> uti = adoptCF(UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, extension.get(), nullptr));
     129        quickLookMIMEType = mimeTypeFromUTITree(uti.get());
     130        if (!quickLookMIMEType)
     131            return mimeType;
     132    }
     133
     134    if (!mimeType || CFStringCompare(mimeType.get(), quickLookMIMEType.get(), kCFCompareCaseInsensitive) != kCFCompareEqualTo) {
     135        CFURLResponseSetMIMEType(cfResponse, quickLookMIMEType.get());
     136        return quickLookMIMEType;
     137    }
     138
     139    return mimeType;
     140}
     141
     142static bool shouldCreateForResponse(CFURLResponseRef cfResponse)
     143{
     144    RetainPtr<CFStringRef> mimeType = adjustMIMETypeForQuickLook(cfResponse);
     145    return [QLPreviewGetSupportedMIMETypesSet() containsObject:(NSString *)mimeType.get()];
    97146}
    98147
     
    397446}
    398447
    399 std::unique_ptr<QuickLookHandle> QuickLookHandle::create(ResourceHandle* handle, NSURLConnection *connection, NSURLResponse *nsResponse, id delegate)
    400 {
    401     ASSERT_ARG(handle, handle);
    402     if (handle->firstRequest().requester() != ResourceRequest::Requester::Main || ![QLPreviewGetSupportedMIMETypesSet() containsObject:[nsResponse MIMEType]])
     448static bool shouldCreate(ResourceHandle& handle, CFURLResponseRef response)
     449{
     450    return handle.firstRequest().requester() == ResourceRequest::Requester::Main && shouldCreateForResponse(response);
     451}
     452
     453std::unique_ptr<QuickLookHandle> QuickLookHandle::create(ResourceHandle& handle, NSURLConnection *connection, NSURLResponse *response, id delegate)
     454{
     455    std::unique_ptr<QuickLookHandle> quickLookHandle(new QuickLookHandle([handle.firstRequest().nsURLRequest(DoNotUpdateHTTPBody) URL], connection, response, delegate));
     456    handle.client()->didCreateQuickLookHandle(*quickLookHandle);
     457    return quickLookHandle;
     458}
     459
     460std::unique_ptr<QuickLookHandle> QuickLookHandle::createIfNecessary(ResourceHandle& handle, NSURLConnection *connection, NSURLResponse *response, id delegate)
     461{
     462    if (!shouldCreate(handle, response._CFURLResponse))
    403463        return nullptr;
    404464
    405     std::unique_ptr<QuickLookHandle> quickLookHandle(new QuickLookHandle([handle->firstRequest().nsURLRequest(DoNotUpdateHTTPBody) URL], connection, nsResponse, delegate));
    406     handle->client()->didCreateQuickLookHandle(*quickLookHandle);
    407     return quickLookHandle;
     465    return create(handle, connection, response, delegate);
    408466}
    409467
    410468#if USE(CFNETWORK)
    411 std::unique_ptr<QuickLookHandle> QuickLookHandle::create(ResourceHandle* handle, SynchronousResourceHandleCFURLConnectionDelegate* connectionDelegate, CFURLResponseRef cfResponse)
    412 {
    413     ASSERT_ARG(handle, handle);
    414     if (handle->firstRequest().requester() != ResourceRequest::Requester::Main || ![QLPreviewGetSupportedMIMETypesSet() containsObject:(NSString *)CFURLResponseGetMIMEType(cfResponse)])
     469std::unique_ptr<QuickLookHandle> QuickLookHandle::createIfNecessary(ResourceHandle& handle, SynchronousResourceHandleCFURLConnectionDelegate* connectionDelegate, CFURLResponseRef cfResponse)
     470{
     471    if (!shouldCreate(handle, cfResponse))
    415472        return nullptr;
    416473
    417     NSURLResponse *nsResponse = [NSURLResponse _responseWithCFURLResponse:cfResponse];
     474    NSURLResponse *response = [NSURLResponse _responseWithCFURLResponse:cfResponse];
    418475    WebQuickLookHandleAsDelegate *delegate = [[[WebQuickLookHandleAsDelegate alloc] initWithConnectionDelegate:connectionDelegate] autorelease];
    419     std::unique_ptr<QuickLookHandle> quickLookHandle(new QuickLookHandle([handle->firstRequest().nsURLRequest(DoNotUpdateHTTPBody) URL], nil, nsResponse, delegate));
    420     handle->client()->didCreateQuickLookHandle(*quickLookHandle);
    421     return quickLookHandle;
     476    return create(handle, nil, response, delegate);
    422477}
    423478
     
    428483#endif
    429484
    430 bool QuickLookHandle::shouldCreateForMIMEType(const String& mimeType)
    431 {
    432     return [QLPreviewGetSupportedMIMETypesSet() containsObject:mimeType];
    433 }
    434 
    435 std::unique_ptr<QuickLookHandle> QuickLookHandle::create(ResourceLoader& loader, const ResourceResponse& response)
    436 {
    437     ASSERT(shouldCreateForMIMEType(response.mimeType()));
     485std::unique_ptr<QuickLookHandle> QuickLookHandle::createIfNecessary(ResourceLoader& loader, NSURLResponse *response)
     486{
     487    bool isMainResourceLoad = loader.documentLoader()->mainResourceLoader() == &loader;
     488    if (!isMainResourceLoad)
     489        return nullptr;
     490
     491    if (!shouldCreateForResponse(response._CFURLResponse))
     492        return nullptr;
    438493
    439494    RetainPtr<WebResourceLoaderQuickLookDelegate> delegate = adoptNS([[WebResourceLoaderQuickLookDelegate alloc] initWithResourceLoader:&loader]);
    440     std::unique_ptr<QuickLookHandle> quickLookHandle(new QuickLookHandle([loader.originalRequest().nsURLRequest(DoNotUpdateHTTPBody) URL], nil, response.nsURLResponse(), delegate.get()));
     495    std::unique_ptr<QuickLookHandle> quickLookHandle(new QuickLookHandle([loader.originalRequest().nsURLRequest(DoNotUpdateHTTPBody) URL], nil, response, delegate.get()));
    441496    [delegate setQuickLookHandle:quickLookHandle.get()];
    442497    loader.didCreateQuickLookHandle(*quickLookHandle);
  • trunk/Source/WebCore/platform/network/ios/WebCoreURLResponseIOS.mm

    r194378 r199644  
    2929#import "config.h"
    3030#import "WebCoreURLResponseIOS.h"
    31 #import "UTIUtilities.h"
    32 #import "WebCoreSystemInterface.h"
    33 
    34 #import "QuickLook.h"
    35 #import "QuickLookSoftLink.h"
    36 #import "SoftLinking.h"
    37 #import <MobileCoreServices/MobileCoreServices.h>
    38 
    39 SOFT_LINK_FRAMEWORK(MobileCoreServices)
    40 
    41 SOFT_LINK(MobileCoreServices, UTTypeCreatePreferredIdentifierForTag, CFStringRef, (CFStringRef inTagClass, CFStringRef inTag, CFStringRef inConformingToUTI), (inTagClass, inTag, inConformingToUTI))
    42 
    43 SOFT_LINK_CONSTANT(MobileCoreServices, kUTTagClassFilenameExtension, CFStringRef)
    44 
    45 #define kUTTagClassFilenameExtension getkUTTagClassFilenameExtension()
    4631
    4732namespace WebCore {
     
    5439        updatedMIMEType = defaultMIMEType().createCFString();
    5540
    56 #if USE(QUICK_LOOK)
    57     // We must ensure that the MIME type is correct, so that QuickLook's web plugin is called when needed.
    58     // We filter the basic MIME types so that we don't do unnecessary work in standard browsing situations.
    59     if (shouldUseQuickLookForMIMEType((NSString *)updatedMIMEType.get())) {
    60         RetainPtr<CFStringRef> suggestedFilename = adoptCF(CFURLResponseCopySuggestedFilename(cfResponse));
    61         RetainPtr<CFStringRef> quickLookMIMEType = adoptCF((CFStringRef)QLTypeCopyBestMimeTypeForFileNameAndMimeType((NSString *)suggestedFilename.get(), (NSString *)mimeType.get()));
    62         if (!quickLookMIMEType) {
    63             auto url = CFURLResponseGetURL(cfResponse);
    64             if ([(NSURL *)url isFileURL]) {
    65                 RetainPtr<CFStringRef> extension = adoptCF(CFURLCopyPathExtension(url));
    66                 if (extension) {
    67                     RetainPtr<CFStringRef> uti = adoptCF(UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, extension.get(), nullptr));
    68                     quickLookMIMEType = mimeTypeFromUTITree(uti.get());
    69                 }
    70             }
    71         }
    72 
    73         if (quickLookMIMEType)
    74             updatedMIMEType = quickLookMIMEType;
    75     }
    76 #endif // USE(QUICK_LOOK)
    7741    if (!mimeType || CFStringCompare(mimeType.get(), updatedMIMEType.get(), kCFCompareCaseInsensitive) != kCFCompareEqualTo)
    7842        CFURLResponseSetMIMEType(cfResponse, updatedMIMEType.get());
  • trunk/Source/WebCore/platform/network/mac/WebCoreResourceHandleAsDelegate.mm

    r194472 r199644  
    163163
    164164#if USE(QUICK_LOOK)
    165     m_handle->setQuickLookHandle(QuickLookHandle::create(m_handle, connection, r, self));
    166     if (m_handle->quickLookHandle())
    167         r = m_handle->quickLookHandle()->nsResponse();
     165    if (auto quickLookHandle = QuickLookHandle::createIfNecessary(*m_handle, connection, r, self)) {
     166        r = quickLookHandle->nsResponse();
     167        m_handle->setQuickLookHandle(WTFMove(quickLookHandle));
     168    }
    168169#endif
    169170   
  • trunk/Source/WebKit2/ChangeLog

    r199628 r199644  
     12016-04-17  Chris Dumez  <cdumez@apple.com>
     2
     3        [WK2][iOS] Do not dlopen() QuickLook in the NetworkProcess
     4        https://bugs.webkit.org/show_bug.cgi?id=156639
     5
     6        Reviewed by Darin Adler.
     7
     8        * WebProcess/Network/WebResourceLoader.cpp:
     9        (WebKit::WebResourceLoader::didReceiveResponse):
     10        Move checks for main resource load and for MIME type inside of
     11        QuickLookHandle::createIfNecessary(), for consistency with the
     12        other QuickLookHandle factory functions.
     13
    1142016-04-16  Dan Bernstein  <mitz@apple.com>
    215
  • trunk/Source/WebKit2/WebProcess/Network/WebResourceLoader.cpp

    r197728 r199644  
    115115    // converted resource isn't yet known. WebResourceLoaderQuickLookDelegate will later call didReceiveResponse upon
    116116    // receiving the converted data.
    117     bool isMainLoad = m_coreLoader->documentLoader()->mainResourceLoader() == m_coreLoader;
    118     if (isMainLoad && QuickLookHandle::shouldCreateForMIMEType(response.mimeType())) {
    119         m_coreLoader->documentLoader()->setQuickLookHandle(QuickLookHandle::create(*m_coreLoader, response));
     117    if (auto quickLookHandle = QuickLookHandle::createIfNecessary(*m_coreLoader, response.nsURLResponse())) {
     118        m_coreLoader->documentLoader()->setQuickLookHandle(WTFMove(quickLookHandle));
    120119        shoudCallCoreLoaderDidReceiveResponse = false;
    121120    }
    122121#endif
     122
    123123    if (shoudCallCoreLoaderDidReceiveResponse)
    124124        m_coreLoader->didReceiveResponse(response);
Note: See TracChangeset for help on using the changeset viewer.