WebKitTools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     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 <JavaScriptCore/JSRetainPtr.h>
       
    30 #include <WebKit2/WKArray.h>
       
    31 #include <WebKit2/WKBundleFrame.h>
       
    32 #include <WebKit2/WKBundlePagePrivate.h>
       
    33 #include <WebKit2/WKRetainPtr.h>
       
    34 #include <WebKit2/WKString.h>
       
    35 #include <WebKit2/WKStringCF.h>
       
    36 #include <wtf/PassOwnPtr.h>
       
    37 #include <wtf/RetainPtr.h>
       
    38 #include <wtf/Vector.h>
       
    39 
       
    40 namespace WTR {
       
    41 
       
    42 static PassOwnPtr<Vector<char> > WKStringToUTF8(WKStringRef wkStringRef)
       
    43 {
       
    44     RetainPtr<CFStringRef> cfString(AdoptCF, WKStringCopyCFString(0, wkStringRef));
       
    45     CFIndex bufferLength = CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfString.get()), kCFStringEncodingUTF8) + 1;
       
    46     OwnPtr<Vector<char> > buffer(new Vector<char>(bufferLength));
       
    47     if (!CFStringGetCString(cfString.get(), buffer->data(), bufferLength, kCFStringEncodingUTF8)) {
       
    48         buffer->shrink(1);
       
    49         (*buffer)[0] = 0;
       
    50     } else
       
    51         buffer->shrink(strlen(buffer->data()) + 1);
       
    52     return buffer.release();
       
    53 }
       
    54 
       
    55 InjectedBundlePage::InjectedBundlePage(WKBundlePageRef page)
       
    56     : m_page(page)
       
    57     , m_isLoading(false)
       
    58 {
       
    59     WKBundlePageLoaderClient loaderClient = {
       
    60         0,
       
    61         this,
       
    62         _didStartProvisionalLoadForFrame,
       
    63         _didReceiveServerRedirectForProvisionalLoadForFrame,
       
    64         _didFailProvisionalLoadWithErrorForFrame,
       
    65         _didCommitLoadForFrame,
       
    66         _didFinishLoadForFrame,
       
    67         _didFailLoadWithErrorForFrame,
       
    68         _didReceiveTitleForFrame,
       
    69         _didClearWindowForFrame
       
    70     };
       
    71     WKBundlePageSetLoaderClient(m_page, &loaderClient);
       
    72 
       
    73     WKBundlePageUIClient uiClient = {
       
    74         0,
       
    75         this,
       
    76         _willAddMessageToConsole,
       
    77         _willSetStatusbarText,
       
    78         _willRunJavaScriptAlert,
       
    79         _willRunJavaScriptConfirm,
       
    80         _willRunJavaScriptPrompt
       
    81     };
       
    82     WKBundlePageSetUIClient(m_page, &uiClient);
       
    83 }
       
    84 
       
    85 InjectedBundlePage::~InjectedBundlePage()
       
    86 {
       
    87 }
       
    88 
       
    89 // Loader Client Callbacks
       
    90 
       
    91 void InjectedBundlePage::_didStartProvisionalLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void *clientInfo)
       
    92 {
       
    93     static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didStartProvisionalLoadForFrame(frame);
       
    94 }
       
    95 
       
    96 void InjectedBundlePage::_didReceiveServerRedirectForProvisionalLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void *clientInfo)
       
    97 {
       
    98     static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didReceiveServerRedirectForProvisionalLoadForFrame(frame);
       
    99 }
       
   100 
       
   101 void InjectedBundlePage::_didFailProvisionalLoadWithErrorForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void *clientInfo)
       
   102 {
       
   103     static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFailProvisionalLoadWithErrorForFrame(frame);
       
   104 }
       
   105 
       
   106 void InjectedBundlePage::_didCommitLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void *clientInfo)
       
   107 {
       
   108     static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didCommitLoadForFrame(frame);
       
   109 }
       
   110 
       
   111 void InjectedBundlePage::_didFinishLoadForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void *clientInfo)
       
   112 {
       
   113     static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFinishLoadForFrame(frame);
       
   114 }
       
   115 
       
   116 void InjectedBundlePage::_didFailLoadWithErrorForFrame(WKBundlePageRef page, WKBundleFrameRef frame, const void *clientInfo)
       
   117 {
       
   118     static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFailLoadWithErrorForFrame(frame);
       
   119 }
       
   120 
       
   121 void InjectedBundlePage::_didReceiveTitleForFrame(WKBundlePageRef page, WKStringRef title, WKBundleFrameRef frame, const void *clientInfo)
       
   122 {
       
   123     static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didReceiveTitleForFrame(title, frame);
       
   124 }
       
   125 
       
   126 void InjectedBundlePage::_didClearWindowForFrame(WKBundlePageRef page, WKBundleFrameRef frame, JSGlobalContextRef context, JSObjectRef window, const void *clientInfo)
       
   127 {
       
   128     static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didClearWindowForFrame(frame, context, window);
       
   129 }
       
   130 
       
   131 void InjectedBundlePage::didStartProvisionalLoadForFrame(WKBundleFrameRef frame)
       
   132 {
       
   133     if (frame == WKBundlePageGetMainFrame(m_page))
       
   134         m_isLoading = true;
       
   135 }
       
   136 
       
   137 void InjectedBundlePage::didReceiveServerRedirectForProvisionalLoadForFrame(WKBundleFrameRef frame)
       
   138 {
       
   139 }
       
   140 
       
   141 void InjectedBundlePage::didFailProvisionalLoadWithErrorForFrame(WKBundleFrameRef frame)
       
   142 {
       
   143 }
       
   144 
       
   145 void InjectedBundlePage::didCommitLoadForFrame(WKBundleFrameRef frame)
       
   146 {
       
   147 }
       
   148 
       
   149 static double numericWindowPropertyValue(WKBundleFrameRef frame, const char* propertyName)
       
   150 {
       
   151     JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
       
   152     JSObjectRef window = JSContextGetGlobalObject(context);
       
   153     JSValueRef exception = 0;
       
   154     JSRetainPtr<JSStringRef> propertyNameString(Adopt, JSStringCreateWithUTF8CString(propertyName));
       
   155     JSValueRef value = JSObjectGetProperty(context, window, propertyNameString.get(), &exception);
       
   156     if (exception)
       
   157         return 0;
       
   158     return JSValueToNumber(context, value, &exception);
       
   159 }
       
   160 
       
   161 enum FrameNamePolicy { ShouldNotIncludeFrameName, ShouldIncludeFrameName };
       
   162 
       
   163 static void dumpFrameScrollPosition(WKBundleFrameRef frame, FrameNamePolicy shouldIncludeFrameName = ShouldNotIncludeFrameName)
       
   164 {
       
   165     double x = numericWindowPropertyValue(frame, "pageXOffset");
       
   166     double y = numericWindowPropertyValue(frame, "pageYOffset");
       
   167     if (fabs(x) > 0.00000001 || fabs(y) > 0.00000001) {
       
   168         if (shouldIncludeFrameName) {
       
   169             WKRetainPtr<WKStringRef> name(AdoptWK, WKBundleFrameCopyName(frame));
       
   170             InjectedBundle::shared().os() << "frame '" << WKStringToUTF8(name.get())->data() << "' ";
       
   171         }
       
   172         InjectedBundle::shared().os() << "scrolled to " << x << "," << y << "\n";
       
   173     }
       
   174 }
       
   175 
       
   176 static void dumpDescendantFrameScrollPositions(WKBundleFrameRef frame)
       
   177 {
       
   178     WKRetainPtr<WKArrayRef> childFrames(AdoptWK, WKBundleFrameCopyChildFrames(frame));
       
   179     size_t size = WKArrayGetSize(childFrames.get());
       
   180     for (size_t i = 0; i < size; ++i) {
       
   181         // FIXME: I don't like that we have to const_cast here. Can we change WKArray?
       
   182         WKBundleFrameRef subframe = static_cast<WKBundleFrameRef>(const_cast<void*>(WKArrayGetItemAtIndex(childFrames.get(), i)));
       
   183         dumpFrameScrollPosition(subframe, ShouldIncludeFrameName);
       
   184         dumpDescendantFrameScrollPositions(subframe);
       
   185     }
       
   186 }
       
   187 
       
   188 void InjectedBundlePage::dumpAllFrameScrollPositions()
       
   189 {
       
   190     WKBundleFrameRef frame = WKBundlePageGetMainFrame(m_page);
       
   191     dumpFrameScrollPosition(frame);
       
   192     dumpDescendantFrameScrollPositions(frame);
       
   193 }
       
   194 
       
   195 void InjectedBundlePage::dump()
       
   196 {
       
   197     InjectedBundle::shared().layoutTestController()->invalidateWaitToDumpWatchdog();
       
   198 
       
   199     if (InjectedBundle::shared().layoutTestController()->shouldDumpAsText()) {
       
   200         // FIXME: Support dumping subframes when layoutTestController()->dumpChildFramesAsText() is true.
       
   201         WKRetainPtr<WKStringRef> innerText(AdoptWK, WKBundleFrameCopyInnerText(WKBundlePageGetMainFrame(m_page)));
       
   202         InjectedBundle::shared().os() << WKStringToUTF8(innerText.get())->data() << "\n";
       
   203     } else {
       
   204         WKRetainPtr<WKStringRef> externalRepresentation(AdoptWK, WKBundlePageCopyRenderTreeExternalRepresentation(m_page));
       
   205         InjectedBundle::shared().os() << WKStringToUTF8(externalRepresentation.get())->data();
       
   206     }
       
   207 
       
   208     if (InjectedBundle::shared().layoutTestController()->shouldDumpAllFrameScrollPositions())
       
   209         dumpAllFrameScrollPositions();
       
   210     else if (InjectedBundle::shared().layoutTestController()->shouldDumpMainFrameScrollPosition())
       
   211         dumpFrameScrollPosition(WKBundlePageGetMainFrame(m_page));
       
   212 
       
   213     InjectedBundle::shared().done();
       
   214 }
       
   215 
       
   216 void InjectedBundlePage::didFinishLoadForFrame(WKBundleFrameRef frame)
       
   217 {
       
   218     if (!WKBundleFrameIsMainFrame(frame))
       
   219         return;
       
   220 
       
   221     m_isLoading = false;
       
   222 
       
   223     if (InjectedBundle::shared().layoutTestController()->waitToDump())
       
   224         return;
       
   225 
       
   226     dump();
       
   227 }
       
   228 
       
   229 void InjectedBundlePage::didFailLoadWithErrorForFrame(WKBundleFrameRef frame)
       
   230 {
       
   231     if (!WKBundleFrameIsMainFrame(frame))
       
   232         return;
       
   233 
       
   234     m_isLoading = false;
       
   235 
       
   236     InjectedBundle::shared().done();
       
   237 }
       
   238 
       
   239 void InjectedBundlePage::didReceiveTitleForFrame(WKStringRef title, WKBundleFrameRef frame)
       
   240 {
       
   241 }
       
   242 
       
   243 void InjectedBundlePage::didClearWindowForFrame(WKBundleFrameRef frame, JSGlobalContextRef context, JSObjectRef window)
       
   244 {
       
   245     JSValueRef exception = 0;
       
   246     InjectedBundle::shared().layoutTestController()->makeWindowObject(context, window, &exception);
       
   247 }
       
   248 
       
   249 // UI Client Callbacks
       
   250 
       
   251 void InjectedBundlePage::_willAddMessageToConsole(WKBundlePageRef page, WKStringRef message, uint32_t lineNumber, const void *clientInfo)
       
   252 {
       
   253     static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willAddMessageToConsole(message, lineNumber);
       
   254 }
       
   255 
       
   256 void InjectedBundlePage::_willSetStatusbarText(WKBundlePageRef page, WKStringRef statusbarText, const void *clientInfo)
       
   257 {
       
   258     static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willSetStatusbarText(statusbarText);
       
   259 }
       
   260 
       
   261 void InjectedBundlePage::_willRunJavaScriptAlert(WKBundlePageRef page, WKStringRef message, WKBundleFrameRef frame, const void *clientInfo)
       
   262 {
       
   263     static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willRunJavaScriptAlert(message, frame);
       
   264 }
       
   265 
       
   266 void InjectedBundlePage::_willRunJavaScriptConfirm(WKBundlePageRef page, WKStringRef message, WKBundleFrameRef frame, const void *clientInfo)
       
   267 {
       
   268     return static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willRunJavaScriptConfirm(message, frame);
       
   269 }
       
   270 
       
   271 void InjectedBundlePage::_willRunJavaScriptPrompt(WKBundlePageRef page, WKStringRef message, WKStringRef defaultValue, WKBundleFrameRef frame, const void *clientInfo)
       
   272 {
       
   273     static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->willRunJavaScriptPrompt(message, defaultValue, frame);
       
   274 }
       
   275 
       
   276 void InjectedBundlePage::willAddMessageToConsole(WKStringRef message, uint32_t lineNumber)
       
   277 {
       
   278     // FIXME: Strip file: urls.
       
   279     InjectedBundle::shared().os() << "CONSOLE MESSAGE: line " << lineNumber << ": " << WKStringToUTF8(message)->data() << "\n";
       
   280 }
       
   281 
       
   282 void InjectedBundlePage::willSetStatusbarText(WKStringRef statusbarText)
       
   283 {
       
   284     if (!InjectedBundle::shared().layoutTestController()->shouldDumpStatusCallbacks())
       
   285         return;
       
   286 
       
   287     InjectedBundle::shared().os() << "UI DELEGATE STATUS CALLBACK: setStatusText:" << WKStringToUTF8(statusbarText)->data() << "\n";
       
   288 }
       
   289 
       
   290 void InjectedBundlePage::willRunJavaScriptAlert(WKStringRef message, WKBundleFrameRef)
       
   291 {
       
   292     InjectedBundle::shared().os() << "ALERT: " << WKStringToUTF8(message)->data() << "\n";
       
   293 }
       
   294 
       
   295 void InjectedBundlePage::willRunJavaScriptConfirm(WKStringRef message, WKBundleFrameRef)
       
   296 {
       
   297     InjectedBundle::shared().os() << "CONFIRM: " << WKStringToUTF8(message)->data() << "\n";
       
   298 }
       
   299 
       
   300 void InjectedBundlePage::willRunJavaScriptPrompt(WKStringRef message, WKStringRef defaultValue, WKBundleFrameRef)
       
   301 {
       
   302     InjectedBundle::shared().os() << "PROMPT: " << WKStringToUTF8(message)->data() << ", default text: " << WKStringToUTF8(defaultValue)->data() <<  "\n";
       
   303 }
       
   304 
       
   305 } // namespace WTR