<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[245896] trunk/Source/WebKit</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/245896">245896</a></dd>
<dt>Author</dt> <dd>cdumez@apple.com</dd>
<dt>Date</dt> <dd>2019-05-30 11:39:19 -0700 (Thu, 30 May 2019)</dd>
</dl>

<h3>Log Message</h3>
<pre>[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:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKitChangeLog">trunk/Source/WebKit/ChangeLog</a></li>
<li><a href="#trunkSourceWebKitUIProcessApplicationStateTrackermm">trunk/Source/WebKit/UIProcess/ApplicationStateTracker.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKitChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/ChangeLog (245895 => 245896)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/ChangeLog    2019-05-30 18:06:09 UTC (rev 245895)
+++ trunk/Source/WebKit/ChangeLog       2019-05-30 18:39:19 UTC (rev 245896)
</span><span class="lines">@@ -1,3 +1,27 @@
</span><ins>+2019-05-30  Chris Dumez  <cdumez@apple.com>
+
+        [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:
+
</ins><span class="cx"> 2019-05-30  Wenson Hsieh  <wenson_hsieh@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Rare crash under `WebPage::shouldIgnoreMetaViewport const` when shrinking to fit content
</span></span></pre></div>
<a id="trunkSourceWebKitUIProcessApplicationStateTrackermm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit/UIProcess/ApplicationStateTracker.mm (245895 => 245896)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit/UIProcess/ApplicationStateTracker.mm 2019-05-30 18:06:09 UTC (rev 245895)
+++ trunk/Source/WebKit/UIProcess/ApplicationStateTracker.mm    2019-05-30 18:39:19 UTC (rev 245896)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> #if PLATFORM(IOS_FAMILY)
</span><span class="cx"> 
</span><span class="cx"> #import "AssertionServicesSPI.h"
</span><ins>+#import "Logging.h"
</ins><span class="cx"> #import "SandboxUtilities.h"
</span><span class="cx"> #import "UIKitSPI.h"
</span><span class="cx"> #import <wtf/ObjCRuntimeExtras.h>
</span><span class="lines">@@ -123,6 +124,7 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    case ApplicationType::Extension:
</ins><span class="cx">     case ApplicationType::ViewService: {
</span><span class="cx">         UIViewController *serviceViewController = nil;
</span><span class="cx"> 
</span><span class="lines">@@ -150,42 +152,20 @@
</span><span class="cx">         if ([serviceViewController._hostApplicationBundleIdentifier isEqualToString:@"com.apple.ios.StoreKitUIService"])
</span><span class="cx">             m_isInBackground = false;
</span><span class="cx"> 
</span><del>-        m_didEnterBackgroundObserver = [notificationCenter addObserverForName:@"_UIViewServiceHostDidEnterBackgroundNotification" object:serviceViewController queue:nil usingBlock:[this](NSNotification *) {
</del><ins>+        RELEASE_LOG(ProcessSuspension, "%{public}s has PID %d, host application PID: %d, isInBackground: %d", _UIApplicationIsExtension() ? "Extension" : "ViewService", getpid(), applicationPID, m_isInBackground);
+
+        m_didEnterBackgroundObserver = [notificationCenter addObserverForName:@"_UIViewServiceHostDidEnterBackgroundNotification" object:serviceViewController queue:nil usingBlock:[this, applicationPID](NSNotification *) {
+            RELEASE_LOG(ProcessSuspension, "%{public}s has PID %d, host application PID: %d, didEnterBackground", _UIApplicationIsExtension() ? "Extension" : "ViewService", getpid(), applicationPID);
</ins><span class="cx">             applicationDidEnterBackground();
</span><span class="cx">         }];
</span><del>-        m_willEnterForegroundObserver = [notificationCenter addObserverForName:@"_UIViewServiceHostWillEnterForegroundNotification" object:serviceViewController queue:nil usingBlock:[this](NSNotification *) {
</del><ins>+        m_willEnterForegroundObserver = [notificationCenter addObserverForName:@"_UIViewServiceHostWillEnterForegroundNotification" object:serviceViewController queue:nil usingBlock:[this, applicationPID](NSNotification *) {
+            RELEASE_LOG(ProcessSuspension, "%{public}s has PID %d, host application PID: %d, willEnterForeground", _UIApplicationIsExtension() ? "Extension" : "ViewService", getpid(), applicationPID);
</ins><span class="cx">             applicationWillEnterForeground();
</span><span class="cx">         }];
</span><span class="cx"> 
</span><span class="cx">         break;
</span><span class="cx">     }
</span><del>-
-    case ApplicationType::Extension: {
-        m_applicationStateMonitor = adoptNS([[BKSApplicationStateMonitor alloc] init]);
-
-        m_isInBackground = isBackgroundState([m_applicationStateMonitor mostElevatedApplicationStateForPID:getpid()]);
-
-        [m_applicationStateMonitor setHandler:[weakThis](NSDictionary *userInfo) {
-            pid_t pid = [userInfo[BKSApplicationStateProcessIDKey] integerValue];
-            if (pid != getpid())
-                return;
-
-            BKSApplicationState newState = (BKSApplicationState)[userInfo[BKSApplicationStateMostElevatedStateForProcessIDKey] unsignedIntValue];
-            bool newInBackground = isBackgroundState(newState);
-
-            dispatch_async(dispatch_get_main_queue(), [weakThis, newInBackground] {
-                auto applicationStateTracker = weakThis.get();
-                if (!applicationStateTracker)
-                    return;
-
-                if (!applicationStateTracker->m_isInBackground && newInBackground)
-                    applicationStateTracker->applicationDidEnterBackground();
-                else if (applicationStateTracker->m_isInBackground && !newInBackground)
-                    applicationStateTracker->applicationWillEnterForeground();
-            });
-        }];
</del><span class="cx">     }
</span><del>-    }
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> ApplicationStateTracker::~ApplicationStateTracker()
</span></span></pre>
</div>
</div>

</body>
</html>