[Webkit-unassigned] [Bug 152386] New: [WK2] Unable to add UserScripts for new Pages when Web Process is running

bugzilla-daemon at webkit.org bugzilla-daemon at webkit.org
Thu Dec 17 04:08:12 PST 2015


https://bugs.webkit.org/show_bug.cgi?id=152386

            Bug ID: 152386
           Summary: [WK2] Unable to add UserScripts for new Pages when Web
                    Process is running
    Classification: Unclassified
           Product: WebKit
           Version: WebKit Nightly Build
          Hardware: All
                OS: All
            Status: NEW
          Severity: Normal
          Priority: P2
         Component: WebKit2
          Assignee: webkit-unassigned at lists.webkit.org
          Reporter: mario at webkit.org
                CC: achristensen at apple.com, andersca at apple.com,
                    cgarcia at igalia.com, darin at apple.com

Created attachment 267555
  --> https://bugs.webkit.org/attachment.cgi?id=267555&action=review
Test case in C (using WebKit2GTK+ API)

[Note that, while I found this issue using WebKitGTK+, it does look to me that the root cause might be a cross-platform issue, so I'm CCing some people from Apple I think might be interested too]

In the last stable relases of WebKitGTK+ (2.10.x, including 2.10.4), it is impossible to get user scripts working on applications that create more than one WebView where all of them share the same web process, since only the first WebView will actually execute the user script's code.

Looking closer at the code, it looks like there is a coordination issue between the UI and the Web process when it comes to adding a reference to the WebPage's WebUserContentController into the associated Web Process, leading to custom user scripts not being added to the WebCore::Page when a new webview is created AFTER its associated web process has been spawned and its running:

Using WebKitGTK+ (sorry again, that's the environment I have) as the code base to describe the process, lets start with the **use case that works** (first WebView):

  1. The first time a WebView loads its contents, it creates internally a WebPageProxy instance in the UI Process to deal with its counterpart in the Web Process (WebPage)
    1.1. Because no WebProcess exists yet at that point, the constructor of WebPageProxy does NOT execute m_process->addWebUserContentControllerProxy() yet, deferring this step until the Web Process has been spawned and reports it finished launching (callback WebPageProxy::processDidFinishLaunching()).
  2. After the Web process starts, a WebPage object is created in the Web Process matching the WebPageProxy object of the UI process related to the page being loaded (same page ID).
    2.1. While creating this WebPage, it registers a "message receiver" callback in the IPC layer to deal with any "AddUserScripts" message that might come later from the UI Process, related to that WebPage
  3. Now, once everything is setup in the Web Process, the WebPageProxy::processDidFinishLaunching() method is finally called, causing the WebUserContentController::AddUserScripts message to be sent from the UI process to the Web Process
    3.1. The message arrives in the WebPage from the Web Process, will be processed properly thanks to the callback installed in step 2.1
    3.2. As a result of processing the AddUserScript message, the WebPage finally installs the UserScript in WebCore::Page
  4. Finally, when the page loads, WebCore runs the user script installed in the WebCore::Page instance as expected and everything works great

Now, the **use case that does NOT work** (any other WebView created for the same web process):

  7. With the Web process already running, creating a new WebView will create a second WebPageProxy instance in the UI Process
    7.1. Because the WebProcess exists and it's running, the constructor of WebPageProxy does execute m_process->addWebUserContentControllerProxy() NOW.
    7.2. Calling addWebUserContentControllerProxy() means that a WebUserContentController::AddUserScripts message is sent now again, from the UI process to the Web Process
    7.3. But at this point, the associated WebPage object has NOT been created in the Web Process yet, meaning that no "message receiver" callback has been installed either to process any AddUserScript message for that page
  8. In the Web process, the AddUserScript message is received anyway and processed by the IPC layer
    8.1. As no "message receiver" callback is found for that pageID, the message is simply discarded and the user script does not get added anywhere
  9. Also in the Web Process, a WebPage is created for the WebPageProxy instance that was just created in the UI process
    9.1. As it happened for the first WebPage created in step 2, a "message receiver" callback is installed now too to deal with incoming AddUserScripts message, which is **too late** now as the message has already arrived and got discarded :( 
  10. Finally, when the page loads, no user script will be executed at all since the WebCore::Page instance does not have it installed, as the message got discarded already (step 8.1).


Last, one final note to say that I only have a WebKitGTK+ environment available, where I can easily reproduce it with any stable release including the last one (2.10.4), BUT I can't reproduce with trunk after r192761 ("[GTK] Use the network process unconditionally"), which initially made me think it could be a GTK-only issue in the stable branch. However, looking a bit closer to the code, my feeling is that enabling the Network Process might not be a "fix" per-se to the issue at hand but something that, for some reason, prevents it from happening, which is why I still reported this bug as a cross-platform problem.

But I might be wrong, of course. Either way, I would appreciate any feedback/help anyone knowing more than me about this could provide 


STEPS TO REPRODUCE (WebKitGTK+ specific, sorry!):

  1. Build the attached test case and run it using a stable release of WebKit2GTK+ (e.g. 2.10.4)
  2. Observe the alert dialog showing up before loading the HTML content
  3. Click on the 'Reload' button several times (feel free to specify a URI too)
  4. Each time you 'Reload' you see the alert dialog showing up before loading
  5. Now click on 'Replace WebView' and let the webview load
  6. After the page loaded, click on the 'Reload' button several times again

EXPECTED OUTCOME

You should see the JavaScript alert dialog showing up each time you reload, before the actual content is rendered on the WebView.

ACTUAL OUTCOME

No JavaScript alert dialog shows up this time before loading after having replaced the webview (step 4), neither it will show up with further attempts to 'Reload' the webview.

Note that manually killing the Web Process from the terminal after Step 4 will make the JavaScript alert dialog to show up again on reload, as a new Web Process will be spawned when creating a new WebView after that.

FREQUENCY: 10/10

Using this test case and the steps mentioned above with WebKit2GTK 2.10.2 and 2.10.4 (versions I tested), I can reproduce the issue 100% of the times

-- 
You are receiving this mail because:
You are the assignee for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.webkit.org/pipermail/webkit-unassigned/attachments/20151217/b55dc468/attachment-0001.html>


More information about the webkit-unassigned mailing list