- Source/WebKit2/ChangeLog +45 lines
Lines 1-3 Source/WebKit2/ChangeLog_sec1
1
2015-07-06  Brent Fulgham  <bfulgham@apple.com>
2
3
        [WK2] UIProcess/WebProcess shutdown logic may have race condition
4
        https://bugs.webkit.org/show_bug.cgi?id=146657
5
        <rdar://problem/21693748>
6
7
        Reviewed by NOBODY (OOPS!).
8
9
        Logging changes to help debug this problem.
10
11
        * Platform/IPC/Connection.cpp:
12
        (IPC::Connection::createSyncMessageEncoder):
13
        (IPC::Connection::sendMessage):
14
        (IPC::Connection::postConnectionDidCloseOnConnectionWorkQueue):
15
        (IPC::Connection::connectionDidClose):
16
        (IPC::Connection::sendOutgoingMessages):
17
        * Platform/IPC/mac/ConnectionMac.mm:
18
        (IPC::ConnectionTerminationWatchdog::watchdogTimerFired):
19
        (IPC::Connection::sendOutgoingMessage):
20
        * Shared/ChildProcess.cpp:
21
        (WebKit::ChildProcess::messageSenderDestinationID):
22
        (WebKit::ChildProcess::terminationTimerFired):
23
        (WebKit::ChildProcess::stopRunLoop):
24
        * Shared/ChildProcessProxy.cpp:
25
        (WebKit::ChildProcessProxy::state):
26
        (WebKit::ChildProcessProxy::sendMessage):
27
        (WebKit::ChildProcessProxy::shutDownProcess):
28
        * UIProcess/WebPageProxy.cpp:
29
        (WebKit::WebPageProxy::setFormClient):
30
        (WebKit::WebPageProxy::setUIClient):
31
        (WebKit::WebPageProxy::close):
32
        (WebKit::WebPageProxy::webProcessWillShutDown):
33
        * UIProcess/WebProcessProxy.cpp:
34
        (WebKit::WebProcessProxy::connectionWillOpen):
35
        (WebKit::WebProcessProxy::processWillShutDown):
36
        (WebKit::WebProcessProxy::removeWebPage):
37
        * WebProcess/WebPage/WebPage.cpp:
38
        (WebKit::WebPage::exitAcceleratedCompositingMode):
39
        (WebKit::WebPage::close):
40
        (WebKit::WebPage::tryClose):
41
        (WebKit::WebPage::didReceiveMessage):
42
        * WebProcess/WebProcess.cpp:
43
        (WebKit::WebProcess::didReceiveMessage):
44
        (WebKit::WebProcess::didClose):
45
1
2015-07-06  Brent Fulgham  <bfulgham@apple.com>
46
2015-07-06  Brent Fulgham  <bfulgham@apple.com>
2
47
3
        Ensure media playback is stopped during page close
48
        Ensure media playback is stopped during page close
- Source/WebKit2/Platform/IPC/Connection.cpp -2 / +17 lines
Lines 344-353 std::unique_ptr<MessageEncoder> Connecti Source/WebKit2/Platform/IPC/Connection.cpp_sec1
344
    return encoder;
344
    return encoder;
345
}
345
}
346
346
347
#include <syslog.h>
348
347
bool Connection::sendMessage(std::unique_ptr<MessageEncoder> encoder, unsigned messageSendFlags, bool alreadyRecordedMessage)
349
bool Connection::sendMessage(std::unique_ptr<MessageEncoder> encoder, unsigned messageSendFlags, bool alreadyRecordedMessage)
348
{
350
{
349
    if (!isValid())
351
    if (!isValid()) {
352
        syslog(LOG_MAKEPRI(LOG_SYSLOG, LOG_CRIT), "<<<<< Connection::sendMessage >>>: %s. INVALID connection. Bailing out.", encoder ? encoder->messageName().data() : "(null)");
350
        return false;
353
        return false;
354
    }
351
355
352
    if (messageSendFlags & DispatchMessageEvenWhenWaitingForSyncReply
356
    if (messageSendFlags & DispatchMessageEvenWhenWaitingForSyncReply
353
        && (!m_onlySendMessagesAsDispatchWhenWaitingForSyncReplyWhenProcessingSuchAMessage
357
        && (!m_onlySendMessagesAsDispatchWhenWaitingForSyncReplyWhenProcessingSuchAMessage
Lines 703-710 void Connection::postConnectionDidCloseO Source/WebKit2/Platform/IPC/Connection.cpp_sec2
703
    });
707
    });
704
}
708
}
705
709
710
#include <syslog.h>
711
706
void Connection::connectionDidClose()
712
void Connection::connectionDidClose()
707
{
713
{
714
    syslog(LOG_MAKEPRI(LOG_SYSLOG, LOG_CRIT), "<<<<< Connection::connectionDidClose >>>");
715
708
    // The connection is now invalid.
716
    // The connection is now invalid.
709
    platformInvalidate();
717
    platformInvalidate();
710
718
Lines 733-738 void Connection::connectionDidClose() Source/WebKit2/Platform/IPC/Connection.cpp_sec3
733
741
734
    RefPtr<Connection> connection(this);
742
    RefPtr<Connection> connection(this);
735
    RunLoop::main().dispatch([connection] {
743
    RunLoop::main().dispatch([connection] {
744
    
745
        syslog(LOG_MAKEPRI(LOG_SYSLOG, LOG_CRIT), "<<<<< Connection::connectionDidClose >>>: Runloop dispatch for didClose handling. Connection client is (%p)", connection->m_client);
746
736
        // If the connection has been explicitly invalidated before dispatchConnectionDidClose was called,
747
        // If the connection has been explicitly invalidated before dispatchConnectionDidClose was called,
737
        // then the client will be null here.
748
        // then the client will be null here.
738
        if (!connection->m_client)
749
        if (!connection->m_client)
Lines 744-749 void Connection::connectionDidClose() Source/WebKit2/Platform/IPC/Connection.cpp_sec4
744
        Client* client = connection->m_client;
755
        Client* client = connection->m_client;
745
        connection->m_client = nullptr;
756
        connection->m_client = nullptr;
746
757
758
        syslog(LOG_MAKEPRI(LOG_SYSLOG, LOG_CRIT), "<<<<< Connection::connectionDidClose >>>: Runloop dispatch calling didClose on client (%p)", connection->m_client);
759
747
        client->didClose(*connection);
760
        client->didClose(*connection);
748
    });
761
    });
749
}
762
}
Lines 755-762 bool Connection::canSendOutgoingMessages Source/WebKit2/Platform/IPC/Connection.cpp_sec5
755
768
756
void Connection::sendOutgoingMessages()
769
void Connection::sendOutgoingMessages()
757
{
770
{
758
    if (!canSendOutgoingMessages())
771
    if (!canSendOutgoingMessages()) {
772
        syslog(LOG_MAKEPRI(LOG_SYSLOG, LOG_CRIT), "<<<<< Connection::sendOutgoingMessages >>> Can't send. Returning.");
759
        return;
773
        return;
774
    }
760
775
761
    while (true) {
776
    while (true) {
762
        std::unique_ptr<MessageEncoder> message;
777
        std::unique_ptr<MessageEncoder> message;
- Source/WebKit2/Platform/IPC/mac/ConnectionMac.mm -2 / +7 lines
Lines 62-68 static const size_t inlineMessageMaxSize Source/WebKit2/Platform/IPC/mac/ConnectionMac.mm_sec1
62
enum {
62
enum {
63
    MessageBodyIsOutOfLine = 1 << 0
63
    MessageBodyIsOutOfLine = 1 << 0
64
};
64
};
65
    
65
66
#include <syslog.h>
67
66
// ConnectionTerminationWatchdog does two things:
68
// ConnectionTerminationWatchdog does two things:
67
// 1) It sets a watchdog timer to kill the peered process.
69
// 1) It sets a watchdog timer to kill the peered process.
68
// 2) On iOS, make the process runnable for the duration of the watchdog
70
// 2) On iOS, make the process runnable for the duration of the watchdog
Lines 87-92 private: Source/WebKit2/Platform/IPC/mac/ConnectionMac.mm_sec2
87
    
89
    
88
    void watchdogTimerFired()
90
    void watchdogTimerFired()
89
    {
91
    {
92
        syslog(LOG_MAKEPRI(LOG_SYSLOG, LOG_CRIT), "!#!#!#!#!#!#! ConnectionTerminationWatchdog::watchdogTimerFired !#!#!#!#!#!#!#!: Killing process.");
90
        xpc_connection_kill(m_xpcConnection.get(), SIGKILL);
93
        xpc_connection_kill(m_xpcConnection.get(), SIGKILL);
91
        delete this;
94
        delete this;
92
    }
95
    }
Lines 284-291 bool Connection::sendOutgoingMessage(std Source/WebKit2/Platform/IPC/mac/ConnectionMac.mm_sec3
284
    char* buffer = &stackBuffer[0];
287
    char* buffer = &stackBuffer[0];
285
    if (messageSize > inlineMessageMaxSize) {
288
    if (messageSize > inlineMessageMaxSize) {
286
        buffer = (char*)mmap(0, messageSize, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
289
        buffer = (char*)mmap(0, messageSize, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
287
        if (buffer == MAP_FAILED)
290
        if (buffer == MAP_FAILED) {
291
            syslog(LOG_MAKEPRI(LOG_SYSLOG, LOG_CRIT), "<<<<< Connection::sendOutgoingMessage >>>: %s. MMAP failed. Returning without sending.", encoder ? encoder->messageName().data() : "(null)");
288
            return false;
292
            return false;
293
        }
289
    }
294
    }
290
295
291
    bool isComplex = (numberOfPortDescriptors + numberOfOOLMemoryDescriptors > 0);
296
    bool isComplex = (numberOfPortDescriptors + numberOfOOLMemoryDescriptors > 0);
- Source/WebKit2/Shared/ChildProcess.cpp -1 / +8 lines
Lines 140-155 uint64_t ChildProcess::messageSenderDest Source/WebKit2/Shared/ChildProcess.cpp_sec1
140
    return 0;
140
    return 0;
141
}
141
}
142
142
143
#include <syslog.h>
144
143
void ChildProcess::terminationTimerFired()
145
void ChildProcess::terminationTimerFired()
144
{
146
{
145
    if (!shouldTerminate())
147
    syslog(LOG_MAKEPRI(LOG_SYSLOG, LOG_CRIT), "<<<<< ChildProcess::terminationTimerFired >>>");
148
    if (!shouldTerminate()) {
149
        syslog(LOG_MAKEPRI(LOG_SYSLOG, LOG_CRIT), "<<<<< ChildProcess::terminationTimerFired >>> shouldTerminate is FALSE");
146
        return;
150
        return;
151
    }
147
152
153
    syslog(LOG_MAKEPRI(LOG_SYSLOG, LOG_CRIT), "<<<<< ChildProcess::stopRunLoop >>>: TERMINATING");
148
    terminate();
154
    terminate();
149
}
155
}
150
156
151
void ChildProcess::stopRunLoop()
157
void ChildProcess::stopRunLoop()
152
{
158
{
159
    syslog(LOG_MAKEPRI(LOG_SYSLOG, LOG_CRIT), "<<<<< ChildProcess::stopRunLoop >>>");
153
    RunLoop::main().stop();
160
    RunLoop::main().stop();
154
}
161
}
155
162
- Source/WebKit2/Shared/ChildProcessProxy.cpp -1 / +12 lines
Lines 87-92 ChildProcessProxy::State ChildProcessPro Source/WebKit2/Shared/ChildProcessProxy.cpp_sec1
87
    return ChildProcessProxy::State::Running;
87
    return ChildProcessProxy::State::Running;
88
}
88
}
89
89
90
#include <syslog.h>
91
90
bool ChildProcessProxy::sendMessage(std::unique_ptr<IPC::MessageEncoder> encoder, unsigned messageSendFlags)
92
bool ChildProcessProxy::sendMessage(std::unique_ptr<IPC::MessageEncoder> encoder, unsigned messageSendFlags)
91
{
93
{
92
    switch (state()) {
94
    switch (state()) {
Lines 99-107 bool ChildProcessProxy::sendMessage(std: Source/WebKit2/Shared/ChildProcessProxy.cpp_sec2
99
        return connection()->sendMessage(WTF::move(encoder), messageSendFlags);
101
        return connection()->sendMessage(WTF::move(encoder), messageSendFlags);
100
102
101
    case State::Terminated:
103
    case State::Terminated:
104
        syslog(LOG_MAKEPRI(LOG_SYSLOG, LOG_CRIT), "<<<<< ChildProcessProxy::sendMessage >>>: Unable to send message: %s. state is Terminated", encoder->messageName().data());
102
        return false;
105
        return false;
103
    }
106
    }
104
107
108
    syslog(LOG_MAKEPRI(LOG_SYSLOG, LOG_CRIT), "<<<<< ChildProcessProxy::sendMessage >>>: Unable to send message: %s. state is not Launching, Running, or Terminated.", encoder->messageName().data());
105
    return false;
109
    return false;
106
}
110
}
107
111
Lines 153-164 void ChildProcessProxy::didFinishLaunchi Source/WebKit2/Shared/ChildProcessProxy.cpp_sec3
153
157
154
void ChildProcessProxy::shutDownProcess()
158
void ChildProcessProxy::shutDownProcess()
155
{
159
{
160
    syslog(LOG_MAKEPRI(LOG_SYSLOG, LOG_CRIT), "<<<<< ChildProcessProxy::shutDownProcess >>>: state is %d, connection is (%p)", state(), m_connection.get());
161
156
    switch (state()) {
162
    switch (state()) {
157
    case State::Launching:
163
    case State::Launching:
158
        m_processLauncher->invalidate();
164
        m_processLauncher->invalidate();
159
        m_processLauncher = nullptr;
165
        m_processLauncher = nullptr;
166
        syslog(LOG_MAKEPRI(LOG_SYSLOG, LOG_CRIT), "<<<<< ChildProcessProxy::shutDownProcess >>>: state is Launching");
160
        break;
167
        break;
161
    case State::Running:
168
    case State::Running:
169
        syslog(LOG_MAKEPRI(LOG_SYSLOG, LOG_CRIT), "<<<<< ChildProcessProxy::shutDownProcess >>>: state is Running. Calling connection->terminateSoon(30)");
162
#if PLATFORM(IOS)
170
#if PLATFORM(IOS)
163
        // On iOS deploy a watchdog in the UI process, since the child process may be suspended.
171
        // On iOS deploy a watchdog in the UI process, since the child process may be suspended.
164
        // If 30s is insufficient for any outstanding activity to complete cleanly, then it will be killed.
172
        // If 30s is insufficient for any outstanding activity to complete cleanly, then it will be killed.
Lines 167-172 void ChildProcessProxy::shutDownProcess( Source/WebKit2/Shared/ChildProcessProxy.cpp_sec4
167
#endif
175
#endif
168
        break;
176
        break;
169
    case State::Terminated:
177
    case State::Terminated:
178
        syslog(LOG_MAKEPRI(LOG_SYSLOG, LOG_CRIT), "<<<<< ChildProcessProxy::shutDownProcess >>>: state is Terminated. Doing nothing.");
170
        return;
179
        return;
171
    }
180
    }
172
181
Lines 175-182 void ChildProcessProxy::shutDownProcess( Source/WebKit2/Shared/ChildProcessProxy.cpp_sec5
175
184
176
    processWillShutDown(*m_connection);
185
    processWillShutDown(*m_connection);
177
186
178
    if (canSendMessage())
187
    if (canSendMessage()) {
188
        syslog(LOG_MAKEPRI(LOG_SYSLOG, LOG_CRIT), "<<<<< ChildProcessProxy::shutDownProcess >>>: sending Message::ChildProcess::ShutDown");
179
        send(Messages::ChildProcess::ShutDown(), 0);
189
        send(Messages::ChildProcess::ShutDown(), 0);
190
    }
180
191
181
    m_connection->invalidate();
192
    m_connection->invalidate();
182
    m_connection = nullptr;
193
    m_connection = nullptr;
- Source/WebKit2/UIProcess/WebPageProxy.cpp +4 lines
Lines 563-568 void WebPageProxy::setFormClient(std::un Source/WebKit2/UIProcess/WebPageProxy.cpp_sec1
563
    m_formClient = WTF::move(formClient);
563
    m_formClient = WTF::move(formClient);
564
}
564
}
565
565
566
#include <syslog.h>
567
566
void WebPageProxy::setUIClient(std::unique_ptr<API::UIClient> uiClient)
568
void WebPageProxy::setUIClient(std::unique_ptr<API::UIClient> uiClient)
567
{
569
{
568
    if (!uiClient) {
570
    if (!uiClient) {
Lines 811-816 void WebPageProxy::close() Source/WebKit2/UIProcess/WebPageProxy.cpp_sec2
811
813
812
    m_webProcessLifetimeTracker.pageWasInvalidated();
814
    m_webProcessLifetimeTracker.pageWasInvalidated();
813
815
816
    syslog(LOG_MAKEPRI(LOG_SYSLOG, LOG_CRIT), "#### WebPageProxy::close ####: Sending WebPage::Close() message to page %llu", m_pageID);
814
    m_process->send(Messages::WebPage::Close(), m_pageID);
817
    m_process->send(Messages::WebPage::Close(), m_pageID);
815
    m_process->removeWebPage(m_pageID);
818
    m_process->removeWebPage(m_pageID);
816
    m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
819
    m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
Lines 3535-3540 void WebPageProxy::connectionWillOpen(IP Source/WebKit2/UIProcess/WebPageProxy.cpp_sec3
3535
3538
3536
void WebPageProxy::webProcessWillShutDown()
3539
void WebPageProxy::webProcessWillShutDown()
3537
{
3540
{
3541
    syslog(LOG_MAKEPRI(LOG_SYSLOG, LOG_CRIT), "<<<<< WebPageProxy::webProcessWillShutDown >>>: Calling m_webProcessLifetimeTracker.webProcessWillShutDown.");
3538
    m_webProcessLifetimeTracker.webProcessWillShutDown();
3542
    m_webProcessLifetimeTracker.webProcessWillShutDown();
3539
}
3543
}
3540
3544
- Source/WebKit2/UIProcess/WebProcessProxy.cpp -2 / +11 lines
Lines 146-151 void WebProcessProxy::connectionWillOpen Source/WebKit2/UIProcess/WebProcessProxy.cpp_sec1
146
        page->connectionWillOpen(connection);
146
        page->connectionWillOpen(connection);
147
}
147
}
148
148
149
#include <syslog.h>
150
149
void WebProcessProxy::processWillShutDown(IPC::Connection& connection)
151
void WebProcessProxy::processWillShutDown(IPC::Connection& connection)
150
{
152
{
151
    ASSERT_UNUSED(connection, this->connection() == &connection);
153
    ASSERT_UNUSED(connection, this->connection() == &connection);
Lines 162-169 void WebProcessProxy::processWillShutDow Source/WebKit2/UIProcess/WebProcessProxy.cpp_sec2
162
        callback();
164
        callback();
163
    m_pendingDeleteWebsiteDataForOriginsCallbacks.clear();
165
    m_pendingDeleteWebsiteDataForOriginsCallbacks.clear();
164
166
165
    for (auto& page : m_pageMap.values())
167
    for (auto& page : m_pageMap.values()) {
168
        syslog(LOG_MAKEPRI(LOG_SYSLOG, LOG_CRIT), "<<<<< ChildProcessProxy::processWillShutDown >>>: Calling page->webProcessWillShutDown.");
166
        page->webProcessWillShutDown();
169
        page->webProcessWillShutDown();
170
    }
167
171
168
    releaseRemainingIconsForPageURLs();
172
    releaseRemainingIconsForPageURLs();
169
}
173
}
Lines 228-233 void WebProcessProxy::addExistingWebPage Source/WebKit2/UIProcess/WebProcessProxy.cpp_sec3
228
232
229
void WebProcessProxy::removeWebPage(uint64_t pageID)
233
void WebProcessProxy::removeWebPage(uint64_t pageID)
230
{
234
{
235
    syslog(LOG_MAKEPRI(LOG_SYSLOG, LOG_CRIT), "#### WebProcessProxy::removeWebPage ####: Removing page %llu", pageID);
236
231
    m_pageMap.remove(pageID);
237
    m_pageMap.remove(pageID);
232
    globalPageMap().remove(pageID);
238
    globalPageMap().remove(pageID);
233
    
239
    
Lines 241-249 void WebProcessProxy::removeWebPage(uint Source/WebKit2/UIProcess/WebProcessProxy.cpp_sec4
241
247
242
    // If this was the last WebPage open in that web process, and we have no other reason to keep it alive, let it go.
248
    // If this was the last WebPage open in that web process, and we have no other reason to keep it alive, let it go.
243
    // We only allow this when using a network process, as otherwise the WebProcess needs to preserve its session state.
249
    // We only allow this when using a network process, as otherwise the WebProcess needs to preserve its session state.
244
    if (!m_processPool->usesNetworkProcess() || state() == State::Terminated || !canTerminateChildProcess())
250
    if (!m_processPool->usesNetworkProcess() || state() == State::Terminated || !canTerminateChildProcess()) {
251
        syslog(LOG_MAKEPRI(LOG_SYSLOG, LOG_CRIT), "#### WebProcessProxy::removeWebPage ####: We CANNOT shut down the WebProcess for page %llu. Because (a) uses network process? (%d), (b) state() == State::Terminated? (%d), (c) Can terminate process? (%d)", pageID, m_processPool->usesNetworkProcess(), state() == State::Terminated, canTerminateChildProcess());
245
        return;
252
        return;
253
    }
246
254
255
    syslog(LOG_MAKEPRI(LOG_SYSLOG, LOG_CRIT), "#### WebProcessProxy::removeWebPage ####: We are allowed to shut down the WebProcess for page %llu. Doing so.", pageID);
247
    shutDown();
256
    shutDown();
248
}
257
}
249
258
- Source/WebKit2/WebProcess/WebProcess.cpp +4 lines
Lines 642-649 void WebProcess::didReceiveMessage(IPC:: Source/WebKit2/WebProcess/WebProcess.cpp_sec1
642
    LOG_ERROR("Unhandled web process message '%s:%s'", decoder.messageReceiverName().toString().data(), decoder.messageName().toString().data());
642
    LOG_ERROR("Unhandled web process message '%s:%s'", decoder.messageReceiverName().toString().data(), decoder.messageName().toString().data());
643
}
643
}
644
644
645
#include <syslog.h>
646
645
void WebProcess::didClose(IPC::Connection&)
647
void WebProcess::didClose(IPC::Connection&)
646
{
648
{
649
    syslog(LOG_MAKEPRI(LOG_SYSLOG, LOG_CRIT), "<<<<< WebProcess::didClose >>>: Received didClose");
650
647
#ifndef NDEBUG
651
#ifndef NDEBUG
648
    m_inDidClose = true;
652
    m_inDidClose = true;
649
653
- Source/WebKit2/WebProcess/WebPage/WebPage.cpp +7 lines
Lines 913-920 void WebPage::exitAcceleratedCompositing Source/WebKit2/WebProcess/WebPage/WebPage.cpp_sec1
913
    m_drawingArea->setRootCompositingLayer(0);
913
    m_drawingArea->setRootCompositingLayer(0);
914
}
914
}
915
915
916
#include <syslog.h>
917
916
void WebPage::close()
918
void WebPage::close()
917
{
919
{
920
    syslog(LOG_MAKEPRI(LOG_SYSLOG, LOG_CRIT), "<<<<< WebPage::close >>>: Closed state: %d", m_isClosed);
921
    
918
    if (m_isClosed)
922
    if (m_isClosed)
919
        return;
923
        return;
920
924
Lines 1004-1009 void WebPage::tryClose() Source/WebKit2/WebProcess/WebPage/WebPage.cpp_sec2
1004
        return;
1008
        return;
1005
    }
1009
    }
1006
1010
1011
    syslog(LOG_MAKEPRI(LOG_SYSLOG, LOG_CRIT), "<<<<< WebPage::tryClose >>>: Sending Message::WebPageProxy::ClosePage(true)");
1007
    send(Messages::WebPageProxy::ClosePage(true));
1012
    send(Messages::WebPageProxy::ClosePage(true));
1008
}
1013
}
1009
1014
Lines 3617-3622 void WebPage::didReceiveMessage(IPC::Con Source/WebKit2/WebProcess/WebPage/WebPage.cpp_sec3
3617
    }
3622
    }
3618
#endif
3623
#endif
3619
3624
3625
    syslog(LOG_MAKEPRI(LOG_SYSLOG, LOG_CRIT), "<<<<< WebPage::didReceiveMessagee >>>: Got a message: %s", decoder.messageName().data());
3626
3620
    didReceiveWebPageMessage(connection, decoder);
3627
    didReceiveWebPageMessage(connection, decoder);
3621
}
3628
}
3622
3629

Return to Bug 146657