Changeset 245896 in webkit


Ignore:
Timestamp:
May 30, 2019 11:39:19 AM (5 years ago)
Author:
Chris Dumez
Message:

[iOS] Third-party extensions using WKWebView are unable to render anything
https://bugs.webkit.org/show_bug.cgi?id=198359
<rdar://problem/51105015>

Reviewed by Brent Fulgham and Geoff Garen.

Third-party extensions using WKWebView are unable to render anything because we do not get notified
when the extension's visibility changes. Because we do not recognize the extension showing the
WebView to be foreground, we do not take a process assertion on behalf of the child processes and
they get suspended before they get a chance to render anything.

The root of the issue is that WebKit was relying on BKSApplicationStateMonitor.handler to get
notified when the extension's state switches between foreground and background. However, the handler
never gets called unless the extension has an appropriate entitlement.

To address the issue, we now use the same logic for extensions and we do for view services.
I have verified that the _UIViewServiceHostDidEnterBackgroundNotification / _UIViewServiceHostWillEnterForegroundNotification
notifications get sent to the extensions (even third-party). We also properly detect MobileSafari as
host application and are able to get MobileSafari's foreground state accurately.

  • UIProcess/ApplicationStateTracker.mm:
Location:
trunk/Source/WebKit
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r245894 r245896  
     12019-05-30  Chris Dumez  <cdumez@apple.com>
     2
     3        [iOS] Third-party extensions using WKWebView are unable to render anything
     4        https://bugs.webkit.org/show_bug.cgi?id=198359
     5        <rdar://problem/51105015>
     6
     7        Reviewed by Brent Fulgham and Geoff Garen.
     8
     9        Third-party extensions using WKWebView are unable to render anything because we do not get notified
     10        when the extension's visibility changes. Because we do not recognize the extension showing the
     11        WebView to be foreground, we do not take a process assertion on behalf of the child processes and
     12        they get suspended before they get a chance to render anything.
     13
     14        The root of the issue is that WebKit was relying on BKSApplicationStateMonitor.handler to get
     15        notified when the extension's state switches between foreground and background. However, the handler
     16        never gets called unless the extension has an appropriate entitlement.
     17
     18        To address the issue, we now use the same logic for extensions and we do for view services.
     19        I have verified that the _UIViewServiceHostDidEnterBackgroundNotification / _UIViewServiceHostWillEnterForegroundNotification
     20        notifications get sent to the extensions (even third-party). We also properly detect MobileSafari as
     21        host application and are able to get MobileSafari's foreground state accurately.
     22
     23        * UIProcess/ApplicationStateTracker.mm:
     24
    1252019-05-30  Wenson Hsieh  <wenson_hsieh@apple.com>
    226
  • trunk/Source/WebKit/UIProcess/ApplicationStateTracker.mm

    r244955 r245896  
    3030
    3131#import "AssertionServicesSPI.h"
     32#import "Logging.h"
    3233#import "SandboxUtilities.h"
    3334#import "UIKitSPI.h"
     
    124125    }
    125126
     127    case ApplicationType::Extension:
    126128    case ApplicationType::ViewService: {
    127129        UIViewController *serviceViewController = nil;
     
    151153            m_isInBackground = false;
    152154
    153         m_didEnterBackgroundObserver = [notificationCenter addObserverForName:@"_UIViewServiceHostDidEnterBackgroundNotification" object:serviceViewController queue:nil usingBlock:[this](NSNotification *) {
     155        RELEASE_LOG(ProcessSuspension, "%{public}s has PID %d, host application PID: %d, isInBackground: %d", _UIApplicationIsExtension() ? "Extension" : "ViewService", getpid(), applicationPID, m_isInBackground);
     156
     157        m_didEnterBackgroundObserver = [notificationCenter addObserverForName:@"_UIViewServiceHostDidEnterBackgroundNotification" object:serviceViewController queue:nil usingBlock:[this, applicationPID](NSNotification *) {
     158            RELEASE_LOG(ProcessSuspension, "%{public}s has PID %d, host application PID: %d, didEnterBackground", _UIApplicationIsExtension() ? "Extension" : "ViewService", getpid(), applicationPID);
    154159            applicationDidEnterBackground();
    155160        }];
    156         m_willEnterForegroundObserver = [notificationCenter addObserverForName:@"_UIViewServiceHostWillEnterForegroundNotification" object:serviceViewController queue:nil usingBlock:[this](NSNotification *) {
     161        m_willEnterForegroundObserver = [notificationCenter addObserverForName:@"_UIViewServiceHostWillEnterForegroundNotification" object:serviceViewController queue:nil usingBlock:[this, applicationPID](NSNotification *) {
     162            RELEASE_LOG(ProcessSuspension, "%{public}s has PID %d, host application PID: %d, willEnterForeground", _UIApplicationIsExtension() ? "Extension" : "ViewService", getpid(), applicationPID);
    157163            applicationWillEnterForeground();
    158164        }];
    159165
    160166        break;
    161     }
    162 
    163     case ApplicationType::Extension: {
    164         m_applicationStateMonitor = adoptNS([[BKSApplicationStateMonitor alloc] init]);
    165 
    166         m_isInBackground = isBackgroundState([m_applicationStateMonitor mostElevatedApplicationStateForPID:getpid()]);
    167 
    168         [m_applicationStateMonitor setHandler:[weakThis](NSDictionary *userInfo) {
    169             pid_t pid = [userInfo[BKSApplicationStateProcessIDKey] integerValue];
    170             if (pid != getpid())
    171                 return;
    172 
    173             BKSApplicationState newState = (BKSApplicationState)[userInfo[BKSApplicationStateMostElevatedStateForProcessIDKey] unsignedIntValue];
    174             bool newInBackground = isBackgroundState(newState);
    175 
    176             dispatch_async(dispatch_get_main_queue(), [weakThis, newInBackground] {
    177                 auto applicationStateTracker = weakThis.get();
    178                 if (!applicationStateTracker)
    179                     return;
    180 
    181                 if (!applicationStateTracker->m_isInBackground && newInBackground)
    182                     applicationStateTracker->applicationDidEnterBackground();
    183                 else if (applicationStateTracker->m_isInBackground && !newInBackground)
    184                     applicationStateTracker->applicationWillEnterForeground();
    185             });
    186         }];
    187167    }
    188168    }
Note: See TracChangeset for help on using the changeset viewer.