Title: [186648] trunk/Source/WebKit2
Revision
186648
Author
ander...@apple.com
Date
2015-07-09 16:32:15 -0700 (Thu, 09 Jul 2015)

Log Message

SafariViewController loads partial webpage or entirely blank webpage
https://bugs.webkit.org/show_bug.cgi?id=146815
rdar://problem/21734757

Reviewed by Dan Bernstein.

* Platform/spi/ios/UIKitSPI.h:
Add _hostProcessIdentifier getter.

* UIProcess/ApplicationStateTracker.h:
Change ApplicationStateTracker to hold on to a WKContentView instead of a UIView.

* UIProcess/ApplicationStateTracker.mm:
(WebKit::applicationType):
Add a helper function that returns the type of application the web view is hosted by (regular
application, view service or extension).

(WebKit::ApplicationStateTracker::ApplicationStateTracker):
Register notifications and update m_isInBackground. For regular applications, just listen for UIApplication notifications.
For view services, walk the view controller hierarchy and find the service view controller and listen for notifications and use
BKS to find the background state of the host application. For extensions, just use BKSApplicationStateMonitor directly.

(WebKit::isViewService): Deleted.

* UIProcess/ios/WKContentView.mm:
(-[WKContentView willMoveToWindow:]):
If we're moving out of a window, null out the state tracker.

(-[WKContentView didMoveToWindow]):
If we moved to a window, create a new state tracker.

(-[WKContentView isBackground]):
Handle a null application state.

(-[WKContentView _commonInitializationWithProcessPool:configuration:]): Deleted.
Don't create the application state here.

Modified Paths

Diff

Modified: trunk/Source/WebKit2/ChangeLog (186647 => 186648)


--- trunk/Source/WebKit2/ChangeLog	2015-07-09 23:29:33 UTC (rev 186647)
+++ trunk/Source/WebKit2/ChangeLog	2015-07-09 23:32:15 UTC (rev 186648)
@@ -1,3 +1,42 @@
+2015-07-09  Anders Carlsson  <ander...@apple.com>
+
+        SafariViewController loads partial webpage or entirely blank webpage
+        https://bugs.webkit.org/show_bug.cgi?id=146815
+        rdar://problem/21734757
+
+        Reviewed by Dan Bernstein.
+
+        * Platform/spi/ios/UIKitSPI.h:
+        Add _hostProcessIdentifier getter.
+
+        * UIProcess/ApplicationStateTracker.h:
+        Change ApplicationStateTracker to hold on to a WKContentView instead of a UIView.
+
+        * UIProcess/ApplicationStateTracker.mm:
+        (WebKit::applicationType):
+        Add a helper function that returns the type of application the web view is hosted by (regular
+        application, view service or extension).
+
+        (WebKit::ApplicationStateTracker::ApplicationStateTracker):
+        Register notifications and update m_isInBackground. For regular applications, just listen for UIApplication notifications.
+        For view services, walk the view controller hierarchy and find the service view controller and listen for notifications and use
+        BKS to find the background state of the host application. For extensions, just use BKSApplicationStateMonitor directly.
+
+        (WebKit::isViewService): Deleted.
+
+        * UIProcess/ios/WKContentView.mm:
+        (-[WKContentView willMoveToWindow:]):
+        If we're moving out of a window, null out the state tracker.
+
+        (-[WKContentView didMoveToWindow]):
+        If we moved to a window, create a new state tracker.
+
+        (-[WKContentView isBackground]):
+        Handle a null application state.
+
+        (-[WKContentView _commonInitializationWithProcessPool:configuration:]): Deleted.
+        Don't create the application state here.
+
 2015-07-09  Dan Bernstein  <m...@apple.com>
 
         [Cocoa] Report the first paint after committing a load as a rendering progress event

Modified: trunk/Source/WebKit2/Platform/spi/ios/UIKitSPI.h (186647 => 186648)


--- trunk/Source/WebKit2/Platform/spi/ios/UIKitSPI.h	2015-07-09 23:29:33 UTC (rev 186647)
+++ trunk/Source/WebKit2/Platform/spi/ios/UIKitSPI.h	2015-07-09 23:32:15 UTC (rev 186648)
@@ -57,6 +57,7 @@
 #import <UIKit/UITextInteractionAssistant_Private.h>
 #import <UIKit/UIViewControllerTransitioning_Private.h>
 #import <UIKit/UIViewController_Private.h>
+#import <UIKit/UIViewController_ViewService.h>
 #import <UIKit/UIView_Private.h>
 #import <UIKit/UIWKSelectionAssistant.h>
 #import <UIKit/UIWKTextInteractionAssistant.h>
@@ -319,6 +320,10 @@
 + (UIViewController *)viewControllerForView:(UIView *)view;
 @end
 
+@interface UIViewController (ViewService)
+- (pid_t)_hostProcessIdentifier;
+@end
+
 @protocol UIViewControllerContextTransitioningEx <UIViewControllerContextTransitioning>
 - (void)__runAlongsideAnimations;
 - (void)_interactivityDidChange:(BOOL)isInteractive;

Modified: trunk/Source/WebKit2/UIProcess/ApplicationStateTracker.h (186647 => 186648)


--- trunk/Source/WebKit2/UIProcess/ApplicationStateTracker.h	2015-07-09 23:29:33 UTC (rev 186647)
+++ trunk/Source/WebKit2/UIProcess/ApplicationStateTracker.h	2015-07-09 23:32:15 UTC (rev 186648)
@@ -33,13 +33,13 @@
 #import <wtf/WeakPtr.h>
 
 OBJC_CLASS BKSApplicationStateMonitor;
-OBJC_CLASS UIView;
+OBJC_CLASS WKContentView;
 
 namespace WebKit {
 
 class ApplicationStateTracker {
 public:
-    ApplicationStateTracker(UIView *, SEL didEnterBackgroundSelector, SEL willEnterForegroundSelector);
+    ApplicationStateTracker(WKContentView *, SEL didEnterBackgroundSelector, SEL willEnterForegroundSelector);
     ~ApplicationStateTracker();
 
     bool isInBackground() const { return m_isInBackground; }
@@ -48,7 +48,7 @@
     void applicationDidEnterBackground();
     void applicationWillEnterForeground();
 
-    WeakObjCPtr<UIView> m_view;
+    WeakObjCPtr<WKContentView> m_view;
     SEL m_didEnterBackgroundSelector;
     SEL m_willEnterForegroundSelector;
 

Modified: trunk/Source/WebKit2/UIProcess/ApplicationStateTracker.mm (186647 => 186648)


--- trunk/Source/WebKit2/UIProcess/ApplicationStateTracker.mm	2015-07-09 23:29:33 UTC (rev 186647)
+++ trunk/Source/WebKit2/UIProcess/ApplicationStateTracker.mm	2015-07-09 23:32:15 UTC (rev 186648)
@@ -30,19 +30,19 @@
 
 #import "AssertionServicesSPI.h"
 #import "UIKitSPI.h"
-#import <UIKit/UIApplication.h>
+#import "WKContentView.h"
 #import <WebCore/SecuritySPI.h>
 #import <wtf/NeverDestroyed.h>
 #import <wtf/ObjcRuntimeExtras.h>
 
+@interface UIWindow (WKDetails)
+- (BOOL)_isHostedInAnotherProcess;
+@end
+
 namespace WebKit {
 
 static bool hasEntitlement(NSString *entitlement)
 {
-#if PLATFORM(IOS_SIMULATOR)
-    // The simulator doesn't support entitlements.
-    return true;
-#else
     auto task = adoptCF(SecTaskCreateFromSelf(CFAllocatorGetDefault()));
     if (!task)
         return false;
@@ -55,18 +55,25 @@
         return false;
 
     return CFBooleanGetValue(static_cast<CFBooleanRef>(value.get()));
-#endif
 }
 
-static bool isViewService()
+enum class ApplicationType {
+    Application,
+    ViewService,
+    Extension,
+};
+
+static ApplicationType applicationType(UIWindow *window)
 {
+    ASSERT(window);
+
     if (_UIApplicationIsExtension())
-        return true;
+        return ApplicationType::Extension;
 
-    if (hasEntitlement(@"com.apple.UIKit.vends-view-services"))
-        return true;
+    if (hasEntitlement(@"com.apple.UIKit.vends-view-services") && window._isHostedInAnotherProcess)
+        return ApplicationType::ViewService;
 
-    return false;
+    return ApplicationType::Application;
 }
 
 static bool isBackgroundState(BKSApplicationState state)
@@ -81,10 +88,11 @@
     }
 }
 
-ApplicationStateTracker::ApplicationStateTracker(UIView *view, SEL didEnterBackgroundSelector, SEL willEnterForegroundSelector)
+ApplicationStateTracker::ApplicationStateTracker(WKContentView *view, SEL didEnterBackgroundSelector, SEL willEnterForegroundSelector)
     : m_view(view)
     , m_didEnterBackgroundSelector(didEnterBackgroundSelector)
     , m_willEnterForegroundSelector(willEnterForegroundSelector)
+    , m_isInBackground(true)
     , m_weakPtrFactory(this)
     , m_didEnterBackgroundObserver(nullptr)
     , m_willEnterForegroundObserver(nullptr)
@@ -92,7 +100,59 @@
     ASSERT([m_view.get() respondsToSelector:m_didEnterBackgroundSelector]);
     ASSERT([m_view.get() respondsToSelector:m_willEnterForegroundSelector]);
 
-    if (isViewService()) {
+    UIWindow *window = [m_view.get() window];
+    ASSERT(window);
+
+    switch (applicationType(window)) {
+    case ApplicationType::Application: {
+        UIApplication *application = [UIApplication sharedApplication];
+        NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
+
+        m_isInBackground = application.applicationState == UIApplicationStateBackground;
+
+        m_didEnterBackgroundObserver = [notificationCenter addObserverForName:UIApplicationDidEnterBackgroundNotification object:application queue:nil usingBlock:[this](NSNotification *) {
+            applicationDidEnterBackground();
+        }];
+
+        m_willEnterForegroundObserver = [notificationCenter addObserverForName:UIApplicationWillEnterForegroundNotification object:application queue:nil usingBlock:[this](NSNotification *) {
+            applicationWillEnterForeground();
+        }];
+        break;
+    }
+
+    case ApplicationType::ViewService: {
+        UIViewController *serviceViewController = nil;
+
+        for (UIView *view = m_view.get().get(); view; view = view.superview) {
+            UIViewController *viewController = [UIViewController viewControllerForView:view];
+
+            if (viewController._hostProcessIdentifier) {
+                serviceViewController = viewController;
+                break;
+            }
+        }
+
+        ASSERT(serviceViewController);
+
+        pid_t applicationPID = serviceViewController._hostProcessIdentifier;
+        ASSERT(applicationPID);
+
+        auto applicationStateMonitor = adoptNS([[BKSApplicationStateMonitor alloc] init]);
+        m_isInBackground = isBackgroundState([m_applicationStateMonitor mostElevatedApplicationStateForPID:applicationPID]);
+
+        NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
+        m_didEnterBackgroundObserver = [notificationCenter addObserverForName:@"_UIViewServiceHostDidEnterBackgroundNotificationName" object:serviceViewController queue:nil usingBlock:[this](NSNotification *) {
+            applicationDidEnterBackground();
+        }];
+
+        m_willEnterForegroundObserver = [notificationCenter addObserverForName:@"_UIViewServiceHostWillEnterForegroundNotificationName" object:serviceViewController queue:nil usingBlock:[this](NSNotification *) {
+            applicationWillEnterForeground();
+        }];
+
+        break;
+    }
+
+    case ApplicationType::Extension: {
         m_applicationStateMonitor = adoptNS([[BKSApplicationStateMonitor alloc] init]);
 
         m_isInBackground = isBackgroundState([m_applicationStateMonitor mostElevatedApplicationStateForPID:getpid()]);
@@ -117,21 +177,8 @@
                     applicationStateTracker->applicationWillEnterForeground();
             });
         }];
-    } else {
-        UIApplication *application = [UIApplication sharedApplication];
-        NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
-
-        m_isInBackground = application.applicationState == UIApplicationStateBackground;
-
-        m_didEnterBackgroundObserver = [notificationCenter addObserverForName:UIApplicationDidEnterBackgroundNotification object:application queue:nil usingBlock:[this](NSNotification *) {
-            applicationDidEnterBackground();
-        }];
-
-        m_willEnterForegroundObserver = [notificationCenter addObserverForName:UIApplicationWillEnterForegroundNotification object:application queue:nil usingBlock:[this](NSNotification *) {
-            applicationWillEnterForeground();
-        }];
-
     }
+    }
 }
 
 ApplicationStateTracker::~ApplicationStateTracker()

Modified: trunk/Source/WebKit2/UIProcess/ios/WKContentView.mm (186647 => 186648)


--- trunk/Source/WebKit2/UIProcess/ios/WKContentView.mm	2015-07-09 23:29:33 UTC (rev 186647)
+++ trunk/Source/WebKit2/UIProcess/ios/WKContentView.mm	2015-07-09 23:32:15 UTC (rev 186648)
@@ -212,8 +212,6 @@
 
     self.layer.hitTestsAsOpaque = YES;
 
-    _applicationStateTracker = std::make_unique<ApplicationStateTracker>(self, @selector(_applicationDidEnterBackground), @selector(_applicationWillEnterForeground));
-
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:[UIApplication sharedApplication]];
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_applicationDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:[UIApplication sharedApplication]];
 
@@ -274,6 +272,11 @@
         if (_webView._allowsLinkPreview)
             [self _unregisterPreviewInWindow:window];
 #endif
+
+        if (!newWindow) {
+            ASSERT(_applicationStateTracker);
+            _applicationStateTracker = nullptr;
+        }
     }
 
     if (newWindow) {
@@ -287,6 +290,15 @@
     }
 }
 
+- (void)didMoveToWindow
+{
+    if (!self.window)
+        return;
+
+    ASSERT(!_applicationStateTracker);
+    _applicationStateTracker = std::make_unique<ApplicationStateTracker>(self, @selector(_applicationDidEnterBackground), @selector(_applicationWillEnterForeground));
+}
+
 - (WKBrowsingContextController *)browsingContextController
 {
     if (!_browsingContextController)
@@ -307,6 +319,9 @@
 
 - (BOOL)isBackground
 {
+    if (!_applicationStateTracker)
+        return YES;
+
     return _applicationStateTracker->isInBackground();
 }
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to