WebAppRenderer.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. //
  2. // Copyright (c) 2014-2016, THUNDERBEAST GAMES LLC All rights reserved
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #include <include/wrapper/cef_message_router.h>
  23. #include "WebAppRenderer.h"
  24. namespace Atomic
  25. {
  26. // Must match the value in client_handler.cc.
  27. static const char kFocusedNodeChangedMessage[] = "ClientRenderer.FocusedNodeChanged";
  28. class WebRenderDelegate : public WebAppRenderer::Delegate
  29. {
  30. public:
  31. static CefRefPtr<CefDictionaryValue> globalProperties_;
  32. static CefString jsMessageQueryFunctionName_;
  33. static CefString jsMessageQueryCancelFunctionName_;
  34. WebRenderDelegate()
  35. : last_node_is_editable_(false)
  36. {
  37. }
  38. virtual void OnWebKitInitialized(CefRefPtr<WebAppRenderer> app) OVERRIDE
  39. {
  40. // Create the renderer-side router for query handling.
  41. CefMessageRouterConfig config;
  42. config.js_query_function = jsMessageQueryFunctionName_.length() ? jsMessageQueryFunctionName_ : "atomicQuery";
  43. config.js_cancel_function = jsMessageQueryCancelFunctionName_.length() ? jsMessageQueryCancelFunctionName_ : "atomicQueryCancel";
  44. message_router_ = CefMessageRouterRendererSide::Create(config);
  45. }
  46. virtual void OnRenderThreadCreated(CefRefPtr<WebAppRenderer> app,
  47. CefRefPtr<CefListValue> extra_info) OVERRIDE
  48. {
  49. // extra info comes from void WebAppBrowser::OnRenderProcessThreadCreated(CefRefPtr<CefListValue> extra_info)
  50. // index 0 is global properties
  51. if (extra_info->GetSize() > 0)
  52. {
  53. if (extra_info->GetType(0) == CefValueType::VTYPE_DICTIONARY)
  54. globalProperties_ = extra_info->GetDictionary(0)->Copy(false);
  55. }
  56. // index 1 is name for jsMessageQuery function
  57. if (extra_info->GetSize() > 1)
  58. {
  59. jsMessageQueryFunctionName_ = extra_info->GetString(1);
  60. }
  61. // index 2 is name for jsMessageQueryCancel function
  62. if (extra_info->GetSize() > 2)
  63. {
  64. jsMessageQueryCancelFunctionName_ = extra_info->GetString(2);
  65. }
  66. }
  67. virtual bool OnBeforeNavigation(CefRefPtr<WebAppRenderer> app,
  68. CefRefPtr<CefBrowser> browser,
  69. CefRefPtr<CefFrame> frame,
  70. CefRefPtr<CefRequest> request,
  71. cef_navigation_type_t navigation_type,
  72. bool is_redirect) OVERRIDE
  73. {
  74. return false;
  75. }
  76. void UpdateGlobalProperties(CefRefPtr<CefV8Context> context)
  77. {
  78. if (!globalProperties_.get())
  79. {
  80. return;
  81. }
  82. context->Enter();
  83. CefDictionaryValue::KeyList keys;
  84. globalProperties_->GetKeys(keys);
  85. for (unsigned i = 0; i < keys.size(); i++)
  86. {
  87. const CefString& globalVarName = keys[i];
  88. CefRefPtr<CefV8Value> globalVar = CefV8Value::CreateObject(nullptr);
  89. CefDictionaryValue::KeyList pkeys;
  90. CefRefPtr<CefDictionaryValue> props = globalProperties_->GetDictionary(globalVarName);
  91. props->GetKeys(pkeys);
  92. for (unsigned j = 0; j < pkeys.size(); j++)
  93. {
  94. const CefString& keyName = pkeys[j];
  95. CefValueType type = props->GetType(keyName);
  96. if (type == VTYPE_BOOL)
  97. {
  98. globalVar->SetValue(keyName, CefV8Value::CreateBool(props->GetBool(keyName)), V8_PROPERTY_ATTRIBUTE_NONE);
  99. }
  100. else if (type == VTYPE_DOUBLE)
  101. {
  102. globalVar->SetValue(keyName, CefV8Value::CreateDouble(props->GetDouble(keyName)), V8_PROPERTY_ATTRIBUTE_NONE);
  103. }
  104. else if (type == VTYPE_STRING)
  105. {
  106. globalVar->SetValue(keyName, CefV8Value::CreateString(props->GetString(keyName)), V8_PROPERTY_ATTRIBUTE_NONE);
  107. }
  108. }
  109. context->GetGlobal()->SetValue(globalVarName, globalVar, V8_PROPERTY_ATTRIBUTE_NONE);
  110. }
  111. context->Exit();
  112. }
  113. virtual void OnBrowserCreated(CefRefPtr<WebAppRenderer> app,
  114. CefRefPtr<CefBrowser> browser) OVERRIDE
  115. {
  116. }
  117. virtual void OnContextCreated(CefRefPtr<WebAppRenderer> app,
  118. CefRefPtr<CefBrowser> browser,
  119. CefRefPtr<CefFrame> frame,
  120. CefRefPtr<CefV8Context> context) OVERRIDE
  121. {
  122. message_router_->OnContextCreated(browser, frame, context);
  123. UpdateGlobalProperties(context);
  124. }
  125. virtual void OnContextReleased(CefRefPtr<WebAppRenderer> app,
  126. CefRefPtr<CefBrowser> browser,
  127. CefRefPtr<CefFrame> frame,
  128. CefRefPtr<CefV8Context> context) OVERRIDE
  129. {
  130. message_router_->OnContextReleased(browser, frame, context);
  131. }
  132. virtual bool OnProcessMessageReceived (
  133. CefRefPtr<WebAppRenderer> app,
  134. CefRefPtr<CefBrowser> browser,
  135. CefProcessId source_process,
  136. CefRefPtr<CefProcessMessage> message) OVERRIDE
  137. {
  138. const CefString& message_name = message->GetName();
  139. if (message_name == "atomic_eval_javascript")
  140. {
  141. CefRefPtr<CefV8Context> context = browser->GetMainFrame()->GetV8Context();
  142. CefRefPtr<CefV8Value> retval;
  143. CefRefPtr<CefV8Exception> exception;
  144. context->Enter();
  145. CefRefPtr<CefV8Value> json = context->GetGlobal()->GetValue("JSON");
  146. if (!json.get() || !json->IsObject())
  147. {
  148. context->Exit();
  149. return false;
  150. }
  151. CefRefPtr<CefV8Value> stringify = json->GetValue("stringify");
  152. if (!stringify.get() || !stringify->IsFunction())
  153. {
  154. context->Exit();
  155. return false;
  156. }
  157. unsigned evalID = (unsigned) message->GetArgumentList()->GetInt(0);
  158. CefString script = message->GetArgumentList()->GetString(1);
  159. bool result = context->Eval(script, retval, exception);
  160. // Create the result message object.
  161. CefRefPtr<CefProcessMessage> msg = CefProcessMessage::Create("atomic_eval_javascript_result");
  162. // Retrieve the argument list object.
  163. CefRefPtr<CefListValue> args = msg->GetArgumentList();
  164. // Populate the argument values.
  165. args->SetInt(0, (int) evalID);
  166. args->SetBool(1, result);
  167. if (result)
  168. {
  169. CefV8ValueList stringifyArgs;
  170. stringifyArgs.push_back(retval);
  171. CefRefPtr<CefV8Value> sjson = stringify->ExecuteFunctionWithContext(context, NULL, stringifyArgs);
  172. if (!sjson.get() || !sjson->IsString())
  173. {
  174. args->SetString(2, "WebAppRenderer::OnProcessMessageReceived() - Error Getting Return JSON");
  175. }
  176. else
  177. {
  178. args->SetString(2, sjson->GetStringValue());
  179. }
  180. }
  181. else
  182. args->SetString(2, exception->GetMessage());
  183. browser->SendProcessMessage(PID_BROWSER, msg);
  184. context->Exit();
  185. return true;
  186. }
  187. else if (message_name == "atomic_set_globalproperties")
  188. {
  189. globalProperties_ = message->GetArgumentList()->GetDictionary(0)->Copy(false);
  190. UpdateGlobalProperties(browser->GetMainFrame()->GetV8Context());
  191. return true;
  192. }
  193. return message_router_->OnProcessMessageReceived(
  194. browser, source_process, message);
  195. }
  196. private:
  197. bool last_node_is_editable_;
  198. // Handles the renderer side of query routing.
  199. CefRefPtr<CefMessageRouterRendererSide> message_router_;
  200. IMPLEMENT_REFCOUNTING(WebRenderDelegate);
  201. };
  202. CefRefPtr<CefDictionaryValue> WebRenderDelegate::globalProperties_;
  203. CefString WebRenderDelegate::jsMessageQueryFunctionName_;
  204. CefString WebRenderDelegate::jsMessageQueryCancelFunctionName_;
  205. WebAppRenderer::WebAppRenderer() {
  206. }
  207. void WebAppRenderer::OnRenderThreadCreated(CefRefPtr<CefListValue> extra_info)
  208. {
  209. delegates_.Push(new WebRenderDelegate());
  210. DelegateSet::Iterator it = delegates_.Begin();
  211. for (; it != delegates_.End(); ++it)
  212. (*it)->OnRenderThreadCreated(this, extra_info);
  213. }
  214. void WebAppRenderer::OnWebKitInitialized()
  215. {
  216. DelegateSet::Iterator it = delegates_.Begin();
  217. for (; it != delegates_.End(); ++it)
  218. (*it)->OnWebKitInitialized(this);
  219. }
  220. void WebAppRenderer::OnBrowserCreated(CefRefPtr<CefBrowser> browser)
  221. {
  222. DelegateSet::Iterator it = delegates_.Begin();
  223. for (; it != delegates_.End(); ++it)
  224. (*it)->OnBrowserCreated(this, browser);
  225. }
  226. void WebAppRenderer::OnBrowserDestroyed(CefRefPtr<CefBrowser> browser)
  227. {
  228. DelegateSet::Iterator it = delegates_.Begin();
  229. for (; it != delegates_.End(); ++it)
  230. (*it)->OnBrowserDestroyed(this, browser);
  231. }
  232. CefRefPtr<CefLoadHandler> WebAppRenderer::GetLoadHandler()
  233. {
  234. CefRefPtr<CefLoadHandler> load_handler;
  235. DelegateSet::Iterator it = delegates_.Begin();
  236. for (; it != delegates_.End() && !load_handler.get(); ++it)
  237. load_handler = (*it)->GetLoadHandler(this);
  238. return load_handler;
  239. }
  240. bool WebAppRenderer::OnBeforeNavigation(CefRefPtr<CefBrowser> browser,
  241. CefRefPtr<CefFrame> frame,
  242. CefRefPtr<CefRequest> request,
  243. NavigationType navigation_type,
  244. bool is_redirect)
  245. {
  246. DelegateSet::Iterator it = delegates_.Begin();
  247. for (; it != delegates_.End(); ++it) {
  248. if ((*it)->OnBeforeNavigation(this, browser, frame, request, navigation_type, is_redirect))
  249. {
  250. return true;
  251. }
  252. }
  253. return false;
  254. }
  255. void WebAppRenderer::OnContextCreated(CefRefPtr<CefBrowser> browser,
  256. CefRefPtr<CefFrame> frame,
  257. CefRefPtr<CefV8Context> context)
  258. {
  259. DelegateSet::Iterator it = delegates_.Begin();
  260. for (; it != delegates_.End(); ++it)
  261. (*it)->OnContextCreated(this, browser, frame, context);
  262. }
  263. void WebAppRenderer::OnContextReleased(CefRefPtr<CefBrowser> browser,
  264. CefRefPtr<CefFrame> frame,
  265. CefRefPtr<CefV8Context> context)
  266. {
  267. DelegateSet::Iterator it = delegates_.Begin();
  268. for (; it != delegates_.End(); ++it)
  269. (*it)->OnContextReleased(this, browser, frame, context);
  270. }
  271. void WebAppRenderer::OnUncaughtException(
  272. CefRefPtr<CefBrowser> browser,
  273. CefRefPtr<CefFrame> frame,
  274. CefRefPtr<CefV8Context> context,
  275. CefRefPtr<CefV8Exception> exception,
  276. CefRefPtr<CefV8StackTrace> stackTrace)
  277. {
  278. DelegateSet::Iterator it = delegates_.Begin();
  279. for (; it != delegates_.End(); ++it)
  280. {
  281. (*it)->OnUncaughtException(this, browser, frame, context, exception, stackTrace);
  282. }
  283. }
  284. void WebAppRenderer::OnFocusedNodeChanged(CefRefPtr<CefBrowser> browser,
  285. CefRefPtr<CefFrame> frame,
  286. CefRefPtr<CefDOMNode> node)
  287. {
  288. DelegateSet::Iterator it = delegates_.Begin();
  289. for (; it != delegates_.End(); ++it)
  290. (*it)->OnFocusedNodeChanged(this, browser, frame, node);
  291. }
  292. bool WebAppRenderer::OnProcessMessageReceived(
  293. CefRefPtr<CefBrowser> browser,
  294. CefProcessId source_process,
  295. CefRefPtr<CefProcessMessage> message)
  296. {
  297. assert(source_process == PID_BROWSER);
  298. bool handled = false;
  299. DelegateSet::Iterator it = delegates_.Begin();
  300. for (; it != delegates_.End() && !handled; ++it) {
  301. handled = (*it)->OnProcessMessageReceived(this, browser, source_process, message);
  302. }
  303. return handled;
  304. }
  305. }