QtBuiltinBundlePage.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /*
  2. * Copyright (C) 2010 Apple Inc. All rights reserved.
  3. * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies)
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
  15. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  16. * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  17. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
  18. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  19. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  20. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  21. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  22. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  23. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  24. * THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include "config.h"
  27. #include "QtBuiltinBundlePage.h"
  28. #include "QtBuiltinBundle.h"
  29. #include "WKArray.h"
  30. #include "WKBundleFrame.h"
  31. #include "WKRetainPtr.h"
  32. #include "WKString.h"
  33. #include "WKStringPrivate.h"
  34. #include "WKStringQt.h"
  35. #include <JavaScript.h>
  36. #include <JavaScriptCore/JSRetainPtr.h>
  37. namespace WebKit {
  38. QtBuiltinBundlePage::QtBuiltinBundlePage(QtBuiltinBundle* bundle, WKBundlePageRef page)
  39. : m_bundle(bundle)
  40. , m_page(page)
  41. , m_navigatorQtObject(0)
  42. , m_navigatorQtObjectEnabled(false)
  43. {
  44. WKBundlePageLoaderClient loaderClient = {
  45. kWKBundlePageLoaderClientCurrentVersion,
  46. this,
  47. 0, // didStartProvisionalLoadForFrame
  48. 0, // didReceiveServerRedirectForProvisionalLoadForFrame
  49. 0, // didFailProvisionalLoadWithErrorForFrame
  50. 0, // didCommitLoadForFrame
  51. 0, // didFinishDocumentLoadForFrame
  52. 0, // didFinishLoadForFrame
  53. 0, // didFailLoadWithErrorForFrame
  54. 0, // didSameDocumentNavigationForFrame
  55. 0, // didReceiveTitleForFrame
  56. 0, // didFirstLayoutForFrame
  57. 0, // didFirstVisuallyNonEmptyLayoutForFrame
  58. 0, // didRemoveFrameFromHierarchy
  59. 0, // didDisplayInsecureContentForFrame
  60. 0, // didRunInsecureContentForFrame
  61. didClearWindowForFrame,
  62. 0, // didCancelClientRedirectForFrame
  63. 0, // willPerformClientRedirectForFrame
  64. 0, // didHandleOnloadEventsForFrame
  65. 0, // didLayoutForFrame
  66. 0, // didNewFirstVisuallyNonEmptyLayoutForFrame
  67. 0, // didDetectXSSForFrame
  68. 0, // shouldGoToBackForwardListItem
  69. 0, // didCreateGlobalObjectForFrame
  70. 0, // willDisconnectDOMWindowExtensionFromGlobalObject
  71. 0, // didReconnectDOMWindowExtensionToGlobalObject
  72. 0, // willDestroyGlobalObjectForDOMWindowExtension
  73. 0, // didFinishProgress
  74. 0, // shouldForceUniversalAccessFromLocalURL
  75. 0, // didReceiveIntentForFrame
  76. 0, // registerIntentServiceForFrame
  77. 0, // didLayout
  78. 0, // featuresUsedInPage
  79. 0, // willLoadURLRequest
  80. 0, // willLoadDataRequest
  81. };
  82. WKBundlePageSetPageLoaderClient(m_page, &loaderClient);
  83. }
  84. QtBuiltinBundlePage::~QtBuiltinBundlePage()
  85. {
  86. if (!m_navigatorQtObject)
  87. return;
  88. WKBundleFrameRef frame = WKBundlePageGetMainFrame(m_page);
  89. JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
  90. JSValueUnprotect(context, m_navigatorQtObject);
  91. }
  92. void QtBuiltinBundlePage::didClearWindowForFrame(WKBundlePageRef page, WKBundleFrameRef frame, WKBundleScriptWorldRef world, const void* clientInfo)
  93. {
  94. static_cast<QtBuiltinBundlePage*>(const_cast<void*>(clientInfo))->didClearWindowForFrame(frame, world);
  95. }
  96. static JSValueRef qt_postMessageCallback(JSContextRef context, JSObjectRef, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef*)
  97. {
  98. // FIXME: should it work regardless of the thisObject?
  99. if (argumentCount < 1 || !JSValueIsString(context, arguments[0]))
  100. return JSValueMakeUndefined(context);
  101. QtBuiltinBundlePage* bundlePage = reinterpret_cast<QtBuiltinBundlePage*>(JSObjectGetPrivate(thisObject));
  102. ASSERT(bundlePage);
  103. // FIXME: needed?
  104. if (!bundlePage->navigatorQtObjectEnabled())
  105. return JSValueMakeUndefined(context);
  106. JSRetainPtr<JSStringRef> jsContents = JSValueToStringCopy(context, arguments[0], 0);
  107. WKRetainPtr<WKStringRef> contents(AdoptWK, WKStringCreateWithJSString(jsContents.get()));
  108. bundlePage->postMessageFromNavigatorQtObject(contents.get());
  109. return JSValueMakeUndefined(context);
  110. }
  111. void QtBuiltinBundlePage::didClearWindowForFrame(WKBundleFrameRef frame, WKBundleScriptWorldRef world)
  112. {
  113. if (!WKBundleFrameIsMainFrame(frame) || WKBundleScriptWorldNormalWorld() != world)
  114. return;
  115. JSGlobalContextRef context = WKBundleFrameGetJavaScriptContextForWorld(frame, world);
  116. registerNavigatorQtObject(context);
  117. }
  118. void QtBuiltinBundlePage::postMessageFromNavigatorQtObject(WKStringRef contents)
  119. {
  120. static WKStringRef messageName = WKStringCreateWithUTF8CString("MessageFromNavigatorQtObject");
  121. WKTypeRef body[] = { page(), contents };
  122. WKRetainPtr<WKArrayRef> messageBody(AdoptWK, WKArrayCreate(body, sizeof(body) / sizeof(WKTypeRef)));
  123. WKBundlePostMessage(m_bundle->toRef(), messageName, messageBody.get());
  124. }
  125. static JSObjectRef createWrappedMessage(JSGlobalContextRef context, WKStringRef data)
  126. {
  127. static JSStringRef dataName = JSStringCreateWithUTF8CString("data");
  128. JSRetainPtr<JSStringRef> jsData = WKStringCopyJSString(data);
  129. JSObjectRef wrappedMessage = JSObjectMake(context, 0, 0);
  130. JSObjectSetProperty(context, wrappedMessage, dataName, JSValueMakeString(context, jsData.get()), kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly, 0);
  131. return wrappedMessage;
  132. }
  133. void QtBuiltinBundlePage::didReceiveMessageToNavigatorQtObject(WKStringRef contents)
  134. {
  135. static JSStringRef onmessageName = JSStringCreateWithUTF8CString("onmessage");
  136. if (!m_navigatorQtObject)
  137. return;
  138. WKBundleFrameRef frame = WKBundlePageGetMainFrame(m_page);
  139. JSGlobalContextRef context = WKBundleFrameGetJavaScriptContext(frame);
  140. JSValueRef onmessageValue = JSObjectGetProperty(context, m_navigatorQtObject, onmessageName, 0);
  141. if (!JSValueIsObject(context, onmessageValue))
  142. return;
  143. JSObjectRef onmessageFunction = JSValueToObject(context, onmessageValue, 0);
  144. if (!JSObjectIsFunction(context, onmessageFunction))
  145. return;
  146. JSObjectRef wrappedMessage = createWrappedMessage(context, contents);
  147. JSObjectCallAsFunction(context, onmessageFunction, 0, 1, &wrappedMessage, 0);
  148. }
  149. void QtBuiltinBundlePage::setNavigatorQtObjectEnabled(bool enabled)
  150. {
  151. if (enabled == m_navigatorQtObjectEnabled)
  152. return;
  153. // Note that this will take effect only after the next page load.
  154. m_navigatorQtObjectEnabled = enabled;
  155. }
  156. void QtBuiltinBundlePage::registerNavigatorQtObject(JSGlobalContextRef context)
  157. {
  158. static JSStringRef postMessageName = JSStringCreateWithUTF8CString("postMessage");
  159. static JSStringRef navigatorName = JSStringCreateWithUTF8CString("navigator");
  160. static JSStringRef qtName = JSStringCreateWithUTF8CString("qt");
  161. if (m_navigatorQtObject)
  162. JSValueUnprotect(context, m_navigatorQtObject);
  163. m_navigatorQtObject = JSObjectMake(context, navigatorQtObjectClass(), this);
  164. JSValueProtect(context, m_navigatorQtObject);
  165. JSObjectRef postMessage = JSObjectMakeFunctionWithCallback(context, postMessageName, qt_postMessageCallback);
  166. JSObjectSetProperty(context, m_navigatorQtObject, postMessageName, postMessage, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly, 0);
  167. JSValueRef navigatorValue = JSObjectGetProperty(context, JSContextGetGlobalObject(context), navigatorName, 0);
  168. if (!JSValueIsObject(context, navigatorValue))
  169. return;
  170. JSObjectRef navigatorObject = JSValueToObject(context, navigatorValue, 0);
  171. JSObjectSetProperty(context, navigatorObject, qtName, m_navigatorQtObject, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly, 0);
  172. }
  173. JSClassRef QtBuiltinBundlePage::navigatorQtObjectClass()
  174. {
  175. static JSClassRef classRef = 0;
  176. if (!classRef) {
  177. const JSClassDefinition navigatorQtObjectClass = kJSClassDefinitionEmpty;
  178. classRef = JSClassCreate(&navigatorQtObjectClass);
  179. }
  180. return classRef;
  181. }
  182. } // namespace WebKit