2010-07-11 Maciej Stachowiak <mjs@apple.com>
[WebKit.git] / WebKitTools / WebKitTestRunner / InjectedBundle / InjectedBundlePage.cpp
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "InjectedBundlePage.h"
27
28 #include "InjectedBundle.h"
29 #include <WebKit2/WKBundleFrame.h>
30 #include <WebKit2/WKBundlePagePrivate.h>
31 #include <WebKit2/WKRetainPtr.h>
32 #include <WebKit2/WKString.h>
33 #include <WebKit2/WKStringCF.h>
34 #include <wtf/RetainPtr.h>
35 #include <wtf/Vector.h>
36
37 namespace WTR {
38
39 InjectedBundlePage::InjectedBundlePage(WKBundlePageRef page)
40     : m_page(page)
41     , m_isLoading(false)
42 {
43     WKBundlePageLoaderClient loaderClient = {
44         0,
45         this,
46         _didStartProvisionalLoadForFrame,
47         _didReceiveServerRedirectForProvisionalLoadForFrame,
48         _didFailProvisionalLoadWithErrorForFrame,
49         _didCommitLoadForFrame,
50         _didFinishLoadForFrame,
51         _didFailLoadWithErrorForFrame,
52         _didReceiveTitleForFrame,
53         _didClearWindowForFrame
54     };
55     WKBundlePageSetLoaderClient(m_page, &loaderClient);
56
57     WKBundlePageUIClient uiClient = {
58         0,
59         this,
60         _addMessageToConsole
61     };
62     WKBundlePageSetUIClient(m_page, &uiClient);
63
64 }
65
66 InjectedBundlePage::~InjectedBundlePage()
67 {
68 }
69
70 // Loader Client Callbacks
71
72 void InjectedBundlePage::_didStartProvisionalLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void *clientInfo)
73 {
74     static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didStartProvisionalLoadForFrame(frame);
75 }
76
77 void InjectedBundlePage::_didReceiveServerRedirectForProvisionalLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void *clientInfo)
78 {
79     static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didReceiveServerRedirectForProvisionalLoadForFrame(frame);
80 }
81
82 void InjectedBundlePage::_didFailProvisionalLoadWithErrorForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void *clientInfo)
83 {
84     static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFailProvisionalLoadWithErrorForFrame(frame);
85 }
86
87 void InjectedBundlePage::_didCommitLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void *clientInfo)
88 {
89     static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didCommitLoadForFrame(frame);
90 }
91
92 void InjectedBundlePage::_didFinishLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void *clientInfo)
93 {
94     static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFinishLoadForFrame(frame);
95 }
96
97 void InjectedBundlePage::_didFailLoadWithErrorForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void *clientInfo)
98 {
99     static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFailLoadWithErrorForFrame(frame);
100 }
101
102 void InjectedBundlePage::_didReceiveTitleForFrame(WKBundlePageRef page, WKStringRef title, WKBundleFrameRef frame, const void *clientInfo)
103 {
104     static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didReceiveTitleForFrame(title, frame);
105 }
106
107 void InjectedBundlePage::_didClearWindowForFrame(WKBundlePageRef page, WKBundleFrameRef frame, JSContextRef ctx, JSObjectRef window, const void *clientInfo)
108 {
109     static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didClearWindowForFrame(frame, ctx, window);
110 }
111
112 void InjectedBundlePage::didStartProvisionalLoadForFrame(WKBundleFrameRef frame)
113 {
114     if (frame == WKBundlePageGetMainFrame(m_page))
115         m_isLoading = true;
116 }
117
118 void InjectedBundlePage::didReceiveServerRedirectForProvisionalLoadForFrame(WKBundleFrameRef frame)
119 {
120 }
121
122 void InjectedBundlePage::didFailProvisionalLoadWithErrorForFrame(WKBundleFrameRef frame)
123 {
124 }
125
126 void InjectedBundlePage::didCommitLoadForFrame(WKBundleFrameRef frame)
127 {
128 }
129
130 static std::auto_ptr<Vector<char> > WKStringToUTF8(WKStringRef wkStringRef)
131 {
132     RetainPtr<CFStringRef> cfString(AdoptCF, WKStringCopyCFString(0, wkStringRef));
133     CFIndex bufferLength = CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfString.get()), kCFStringEncodingUTF8) + 1;
134     std::auto_ptr<Vector<char> > buffer(new Vector<char>(bufferLength));
135     if (!CFStringGetCString(cfString.get(), buffer->data(), bufferLength, kCFStringEncodingUTF8)) {
136         buffer->shrink(1);
137         (*buffer)[0] = 0;
138     } else
139         buffer->shrink(strlen(buffer->data()) + 1);
140     return buffer;
141 }
142
143 void InjectedBundlePage::dump()
144 {
145     InjectedBundle::shared().layoutTestController()->invalidateWaitToDumpWatchdog();
146
147     if (InjectedBundle::shared().layoutTestController()->dumpAsText()) {
148         // FIXME: Support dumping subframes when layoutTestController()->dumpChildFramesAsText() is true.
149         WKRetainPtr<WKStringRef> innerText(AdoptWK, WKBundleFrameCopyInnerText(WKBundlePageGetMainFrame(m_page)));
150         std::auto_ptr<Vector<char> > utf8InnerText = WKStringToUTF8(innerText.get());
151         InjectedBundle::shared().os() << utf8InnerText->data() << "\n";
152     } else {
153         WKRetainPtr<WKStringRef> externalRepresentation(AdoptWK, WKBundlePageCopyRenderTreeExternalRepresentation(m_page));
154         std::auto_ptr<Vector<char> > utf8externalRepresentation = WKStringToUTF8(externalRepresentation.get());
155         InjectedBundle::shared().os() << utf8externalRepresentation->data();
156     }
157     InjectedBundle::shared().done();
158 }
159
160 void InjectedBundlePage::didFinishLoadForFrame(WKBundleFrameRef frame)
161 {
162     if (!WKBundleFrameIsMainFrame(frame))
163         return;
164
165     m_isLoading = false;
166
167     if (InjectedBundle::shared().layoutTestController()->waitToDump())
168         return;
169
170     dump();
171 }
172
173 void InjectedBundlePage::didFailLoadWithErrorForFrame(WKBundleFrameRef frame)
174 {
175     if (!WKBundleFrameIsMainFrame(frame))
176         return;
177
178     m_isLoading = false;
179
180     InjectedBundle::shared().done();
181 }
182
183 void InjectedBundlePage::didReceiveTitleForFrame(WKStringRef title, WKBundleFrameRef frame)
184 {
185 }
186
187 void InjectedBundlePage::didClearWindowForFrame(WKBundleFrameRef frame, JSContextRef ctx, JSObjectRef window)
188 {
189     JSValueRef exception = 0;
190     InjectedBundle::shared().layoutTestController()->makeWindowObject(ctx, window, &exception);
191 }
192
193 // UI Client Callbacks
194
195 void InjectedBundlePage::_addMessageToConsole(WKBundlePageRef page, WKStringRef message, uint32_t lineNumber, const void *clientInfo)
196 {
197     static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->addMessageToConsole(message, lineNumber);
198 }
199
200 void InjectedBundlePage::addMessageToConsole(WKStringRef message, uint32_t lineNumber)
201 {
202     // FIXME: Strip file: urls.
203     std::auto_ptr<Vector<char> > utf8Message = WKStringToUTF8(message);
204     InjectedBundle::shared().os() << "CONSOLE MESSAGE: line " << lineNumber << ": " << utf8Message->data() << "\n";
205 }
206
207 } // namespace WTR