Changeset 201246 in webkit


Ignore:
Timestamp:
May 21, 2016 4:52:37 PM (8 years ago)
Author:
aestes@apple.com
Message:

REGRESSION (r188642): All pages are blank when printing a webpage in iOS Safari
https://bugs.webkit.org/show_bug.cgi?id=157924
rdar://problem/22524550

Reviewed by Sam Weinig.

When UIPrintInteractionController asks WKWebView to print a webpage, it does so in several phases. First we're
asked to compute the page count, followed later by a series of messages asking us to draw each page into a
provided CGContext.

When asked for the page count, we send a message to the Web process instructing it to compute and
return the page count synchronously and then immediately start drawing the page for printing. If the drawing has
finished by the time we're asked to print the first page, then we can do so without waiting. But if it hasn't
then we block by calling Connection::waitForMessage(), passing std::chromo::milliseconds::max() as the relative
timeout.

Prior to r188642, Connection::waitForMessage() called std::condition_variable::wait_for(), which takes a
relative timeout value. r188642 replaced this with WTF::Condition::waitUntil(), which takes an absolute timeout
instead. To convert from relative to absolute, this line was added to Connection::waitForMessage():

Condition::Clock::time_point absoluteTimeout = Condition::Clock::now() + timeout;

std::chrono will convert both operands to a common duration type before performing the addition. When timeout
equals something very large, like milliseconds::max(), this conversion results in signed integer overflow,
giving absoluteTimeout a value less than Clock::now() and making waitForMessage time out immediately.

To fix this, compute how many milliseconds remain on our clock, and add the smaller of that and the timeout
value to Clock::now() to arrive at an absolute timeout.

  • Platform/IPC/Connection.cpp:

(IPC::Connection::waitForMessage):

  • UIProcess/API/Cocoa/WKWebView.mm:

(-[WKWebView _printedDocument]): Removed an unnecessary nanoseconds-to-milliseconds conversion.

Location:
trunk/Source/WebKit2
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit2/ChangeLog

    r201227 r201246  
     12016-05-21  Andy Estes  <aestes@apple.com>
     2
     3        REGRESSION (r188642): All pages are blank when printing a webpage in iOS Safari
     4        https://bugs.webkit.org/show_bug.cgi?id=157924
     5        rdar://problem/22524550
     6
     7        Reviewed by Sam Weinig.
     8
     9        When UIPrintInteractionController asks WKWebView to print a webpage, it does so in several phases. First we're
     10        asked to compute the page count, followed later by a series of messages asking us to draw each page into a
     11        provided CGContext.
     12
     13        When asked for the page count, we send a message to the Web process instructing it to compute and
     14        return the page count synchronously and then immediately start drawing the page for printing. If the drawing has
     15        finished by the time we're asked to print the first page, then we can do so without waiting. But if it hasn't
     16        then we block by calling Connection::waitForMessage(), passing std::chromo::milliseconds::max() as the relative
     17        timeout.
     18       
     19        Prior to r188642, Connection::waitForMessage() called std::condition_variable::wait_for(), which takes a
     20        relative timeout value. r188642 replaced this with WTF::Condition::waitUntil(), which takes an absolute timeout
     21        instead. To convert from relative to absolute, this line was added to Connection::waitForMessage():
     22
     23            Condition::Clock::time_point absoluteTimeout = Condition::Clock::now() + timeout;
     24
     25        std::chrono will convert both operands to a common duration type before performing the addition. When timeout
     26        equals something very large, like milliseconds::max(), this conversion results in signed integer overflow,
     27        giving absoluteTimeout a value less than Clock::now() and making waitForMessage time out immediately.
     28       
     29        To fix this, compute how many milliseconds remain on our clock, and add the smaller of that and the timeout
     30        value to Clock::now() to arrive at an absolute timeout.
     31
     32        * Platform/IPC/Connection.cpp:
     33        (IPC::Connection::waitForMessage):
     34        * UIProcess/API/Cocoa/WKWebView.mm:
     35        (-[WKWebView _printedDocument]): Removed an unnecessary nanoseconds-to-milliseconds conversion.
     36
    1372016-05-20  Enrica Casucci  <enrica@apple.com>
    238
  • trunk/Source/WebKit2/Platform/IPC/Connection.cpp

    r197728 r201246  
    433433    }
    434434
     435    // Clamp the timeout to however much time is remaining on our clock.
     436    auto now = Condition::Clock::now();
     437    auto remainingClockTime = std::chrono::duration_cast<std::chrono::milliseconds>(Condition::Clock::time_point::max() - now);
     438    auto absoluteTimeout = now + std::min(remainingClockTime, timeout);
     439
    435440    // Now wait for it to be set.
    436     Condition::Clock::time_point absoluteTimeout = Condition::Clock::now() + timeout;
    437441    while (true) {
    438442        std::unique_lock<Lock> lock(m_waitForMessageMutex);
  • trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm

    r201187 r201246  
    45514551}
    45524552
    4553 // FIXME: milliseconds::max() overflows when converted to nanoseconds, causing condition_variable::wait_for() to believe
    4554 // a timeout occurred on any spurious wakeup. Use nanoseconds::max() (converted to ms) to avoid this. We should perhaps
    4555 // change waitForAndDispatchImmediately() to take nanoseconds to avoid this issue.
    4556 static constexpr std::chrono::milliseconds didFinishLoadingTimeout = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::nanoseconds::max());
    4557 
    45584553- (CGPDFDocumentRef)_printedDocument
    45594554{
     
    45644559
    45654560    if (_pageIsPrintingToPDF) {
    4566         if (!_page->process().connection()->waitForAndDispatchImmediately<Messages::WebPageProxy::DidFinishDrawingPagesToPDF>(_page->pageID(), didFinishLoadingTimeout)) {
     4561        if (!_page->process().connection()->waitForAndDispatchImmediately<Messages::WebPageProxy::DidFinishDrawingPagesToPDF>(_page->pageID(), std::chrono::milliseconds::max())) {
    45674562            ASSERT_NOT_REACHED();
    45684563            return nullptr;
Note: See TracChangeset for help on using the changeset viewer.