WebAppRenderer.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  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. WebRenderDelegate()
  33. : last_node_is_editable_(false)
  34. {
  35. }
  36. virtual void OnWebKitInitialized(CefRefPtr<WebAppRenderer> app) OVERRIDE
  37. {
  38. // Create the renderer-side router for query handling.
  39. CefMessageRouterConfig config;
  40. config.js_query_function = "atomicQuery";
  41. config.js_cancel_function = "atomicQueryCancel";
  42. message_router_ = CefMessageRouterRendererSide::Create(config);
  43. }
  44. virtual void OnRenderThreadCreated(CefRefPtr<WebAppRenderer> app,
  45. CefRefPtr<CefListValue> extra_info) OVERRIDE
  46. {
  47. // extra info comes from void WebAppBrowser::OnRenderProcessThreadCreated(CefRefPtr<CefListValue> extra_info)
  48. if (extra_info->GetSize() > 0)
  49. {
  50. // index 0 is global properties
  51. globalProperties_ = extra_info->GetDictionary(0)->Copy(false);
  52. }
  53. }
  54. virtual bool OnBeforeNavigation(CefRefPtr<WebAppRenderer> app,
  55. CefRefPtr<CefBrowser> browser,
  56. CefRefPtr<CefFrame> frame,
  57. CefRefPtr<CefRequest> request,
  58. cef_navigation_type_t navigation_type,
  59. bool is_redirect) OVERRIDE
  60. {
  61. return false;
  62. }
  63. void UpdateGlobalProperties(CefRefPtr<CefV8Context> context)
  64. {
  65. if (!globalProperties_.get())
  66. {
  67. return;
  68. }
  69. context->Enter();
  70. CefDictionaryValue::KeyList keys;
  71. globalProperties_->GetKeys(keys);
  72. for (unsigned i = 0; i < keys.size(); i++)
  73. {
  74. const CefString& globalVarName = keys[i];
  75. CefRefPtr<CefV8Value> globalVar = CefV8Value::CreateObject(nullptr);
  76. CefDictionaryValue::KeyList pkeys;
  77. CefRefPtr<CefDictionaryValue> props = globalProperties_->GetDictionary(globalVarName);
  78. props->GetKeys(pkeys);
  79. for (unsigned j = 0; j < pkeys.size(); j++)
  80. {
  81. const CefString& keyName = pkeys[j];
  82. CefValueType type = props->GetType(keyName);
  83. if (type == VTYPE_BOOL)
  84. {
  85. globalVar->SetValue(keyName, CefV8Value::CreateBool(props->GetBool(keyName)), V8_PROPERTY_ATTRIBUTE_NONE);
  86. }
  87. else if (type == VTYPE_DOUBLE)
  88. {
  89. globalVar->SetValue(keyName, CefV8Value::CreateDouble(props->GetDouble(keyName)), V8_PROPERTY_ATTRIBUTE_NONE);
  90. }
  91. else if (type == VTYPE_STRING)
  92. {
  93. globalVar->SetValue(keyName, CefV8Value::CreateString(props->GetString(keyName)), V8_PROPERTY_ATTRIBUTE_NONE);
  94. }
  95. }
  96. context->GetGlobal()->SetValue(globalVarName, globalVar, V8_PROPERTY_ATTRIBUTE_NONE);
  97. }
  98. context->Exit();
  99. }
  100. virtual void OnBrowserCreated(CefRefPtr<WebAppRenderer> app,
  101. CefRefPtr<CefBrowser> browser) OVERRIDE
  102. {
  103. }
  104. virtual void OnContextCreated(CefRefPtr<WebAppRenderer> app,
  105. CefRefPtr<CefBrowser> browser,
  106. CefRefPtr<CefFrame> frame,
  107. CefRefPtr<CefV8Context> context) OVERRIDE
  108. {
  109. message_router_->OnContextCreated(browser, frame, context);
  110. UpdateGlobalProperties(context);
  111. }
  112. virtual void OnContextReleased(CefRefPtr<WebAppRenderer> app,
  113. CefRefPtr<CefBrowser> browser,
  114. CefRefPtr<CefFrame> frame,
  115. CefRefPtr<CefV8Context> context) OVERRIDE
  116. {
  117. message_router_->OnContextReleased(browser, frame, context);
  118. }
  119. virtual bool OnProcessMessageReceived (
  120. CefRefPtr<WebAppRenderer> app,
  121. CefRefPtr<CefBrowser> browser,
  122. CefProcessId source_process,
  123. CefRefPtr<CefProcessMessage> message) OVERRIDE
  124. {
  125. const CefString& message_name = message->GetName();
  126. if (message_name == "atomic_eval_javascript")
  127. {
  128. CefRefPtr<CefV8Context> context = browser->GetMainFrame()->GetV8Context();
  129. CefRefPtr<CefV8Value> retval;
  130. CefRefPtr<CefV8Exception> exception;
  131. context->Enter();
  132. CefRefPtr<CefV8Value> json = context->GetGlobal()->GetValue("JSON");
  133. if (!json.get() || !json->IsObject())
  134. {
  135. context->Exit();
  136. return false;
  137. }
  138. CefRefPtr<CefV8Value> stringify = json->GetValue("stringify");
  139. if (!stringify.get() || !stringify->IsFunction())
  140. {
  141. context->Exit();
  142. return false;
  143. }
  144. unsigned evalID = (unsigned) message->GetArgumentList()->GetInt(0);
  145. CefString script = message->GetArgumentList()->GetString(1);
  146. bool result = context->Eval(script, retval, exception);
  147. // Create the result message object.
  148. CefRefPtr<CefProcessMessage> msg = CefProcessMessage::Create("atomic_eval_javascript_result");
  149. // Retrieve the argument list object.
  150. CefRefPtr<CefListValue> args = msg->GetArgumentList();
  151. // Populate the argument values.
  152. args->SetInt(0, (int) evalID);
  153. args->SetBool(1, result);
  154. if (result)
  155. {
  156. CefV8ValueList stringifyArgs;
  157. stringifyArgs.push_back(retval);
  158. CefRefPtr<CefV8Value> sjson = stringify->ExecuteFunctionWithContext(context, NULL, stringifyArgs);
  159. if (!sjson.get() || !sjson->IsString())
  160. {
  161. args->SetString(2, "WebAppRenderer::OnProcessMessageReceived() - Error Getting Return JSON");
  162. }
  163. else
  164. {
  165. args->SetString(2, sjson->GetStringValue());
  166. }
  167. }
  168. else
  169. args->SetString(2, exception->GetMessage());
  170. browser->SendProcessMessage(PID_BROWSER, msg);
  171. context->Exit();
  172. return true;
  173. }
  174. else if (message_name == "atomic_set_globalproperties")
  175. {
  176. globalProperties_ = message->GetArgumentList()->GetDictionary(0)->Copy(false);
  177. UpdateGlobalProperties(browser->GetMainFrame()->GetV8Context());
  178. return true;
  179. }
  180. return message_router_->OnProcessMessageReceived(
  181. browser, source_process, message);
  182. }
  183. private:
  184. bool last_node_is_editable_;
  185. // Handles the renderer side of query routing.
  186. CefRefPtr<CefMessageRouterRendererSide> message_router_;
  187. IMPLEMENT_REFCOUNTING(WebRenderDelegate);
  188. };
  189. CefRefPtr<CefDictionaryValue> WebRenderDelegate::globalProperties_;
  190. WebAppRenderer::WebAppRenderer() {
  191. }
  192. void WebAppRenderer::OnRenderThreadCreated(CefRefPtr<CefListValue> extra_info)
  193. {
  194. delegates_.Push(new WebRenderDelegate());
  195. DelegateSet::Iterator it = delegates_.Begin();
  196. for (; it != delegates_.End(); ++it)
  197. (*it)->OnRenderThreadCreated(this, extra_info);
  198. }
  199. void WebAppRenderer::OnWebKitInitialized()
  200. {
  201. DelegateSet::Iterator it = delegates_.Begin();
  202. for (; it != delegates_.End(); ++it)
  203. (*it)->OnWebKitInitialized(this);
  204. }
  205. void WebAppRenderer::OnBrowserCreated(CefRefPtr<CefBrowser> browser)
  206. {
  207. DelegateSet::Iterator it = delegates_.Begin();
  208. for (; it != delegates_.End(); ++it)
  209. (*it)->OnBrowserCreated(this, browser);
  210. }
  211. void WebAppRenderer::OnBrowserDestroyed(CefRefPtr<CefBrowser> browser)
  212. {
  213. DelegateSet::Iterator it = delegates_.Begin();
  214. for (; it != delegates_.End(); ++it)
  215. (*it)->OnBrowserDestroyed(this, browser);
  216. }
  217. CefRefPtr<CefLoadHandler> WebAppRenderer::GetLoadHandler()
  218. {
  219. CefRefPtr<CefLoadHandler> load_handler;
  220. DelegateSet::Iterator it = delegates_.Begin();
  221. for (; it != delegates_.End() && !load_handler.get(); ++it)
  222. load_handler = (*it)->GetLoadHandler(this);
  223. return load_handler;
  224. }
  225. bool WebAppRenderer::OnBeforeNavigation(CefRefPtr<CefBrowser> browser,
  226. CefRefPtr<CefFrame> frame,
  227. CefRefPtr<CefRequest> request,
  228. NavigationType navigation_type,
  229. bool is_redirect)
  230. {
  231. DelegateSet::Iterator it = delegates_.Begin();
  232. for (; it != delegates_.End(); ++it) {
  233. if ((*it)->OnBeforeNavigation(this, browser, frame, request, navigation_type, is_redirect))
  234. {
  235. return true;
  236. }
  237. }
  238. return false;
  239. }
  240. void WebAppRenderer::OnContextCreated(CefRefPtr<CefBrowser> browser,
  241. CefRefPtr<CefFrame> frame,
  242. CefRefPtr<CefV8Context> context)
  243. {
  244. DelegateSet::Iterator it = delegates_.Begin();
  245. for (; it != delegates_.End(); ++it)
  246. (*it)->OnContextCreated(this, browser, frame, context);
  247. }
  248. void WebAppRenderer::OnContextReleased(CefRefPtr<CefBrowser> browser,
  249. CefRefPtr<CefFrame> frame,
  250. CefRefPtr<CefV8Context> context)
  251. {
  252. DelegateSet::Iterator it = delegates_.Begin();
  253. for (; it != delegates_.End(); ++it)
  254. (*it)->OnContextReleased(this, browser, frame, context);
  255. }
  256. void WebAppRenderer::OnUncaughtException(
  257. CefRefPtr<CefBrowser> browser,
  258. CefRefPtr<CefFrame> frame,
  259. CefRefPtr<CefV8Context> context,
  260. CefRefPtr<CefV8Exception> exception,
  261. CefRefPtr<CefV8StackTrace> stackTrace)
  262. {
  263. DelegateSet::Iterator it = delegates_.Begin();
  264. for (; it != delegates_.End(); ++it)
  265. {
  266. (*it)->OnUncaughtException(this, browser, frame, context, exception, stackTrace);
  267. }
  268. }
  269. void WebAppRenderer::OnFocusedNodeChanged(CefRefPtr<CefBrowser> browser,
  270. CefRefPtr<CefFrame> frame,
  271. CefRefPtr<CefDOMNode> node)
  272. {
  273. DelegateSet::Iterator it = delegates_.Begin();
  274. for (; it != delegates_.End(); ++it)
  275. (*it)->OnFocusedNodeChanged(this, browser, frame, node);
  276. }
  277. bool WebAppRenderer::OnProcessMessageReceived(
  278. CefRefPtr<CefBrowser> browser,
  279. CefProcessId source_process,
  280. CefRefPtr<CefProcessMessage> message)
  281. {
  282. assert(source_process == PID_BROWSER);
  283. bool handled = false;
  284. DelegateSet::Iterator it = delegates_.Begin();
  285. for (; it != delegates_.End() && !handled; ++it) {
  286. handled = (*it)->OnProcessMessageReceived(this, browser, source_process, message);
  287. }
  288. return handled;
  289. }
  290. }