Fix crash in web view on android

This commit is contained in:
dimon4eg 2015-10-15 16:43:53 +03:00
parent e789ab97be
commit ee3c000b43
1 changed files with 57 additions and 26 deletions

View File

@ -35,8 +35,11 @@
#include "UIWebView.h" #include "UIWebView.h"
#include "platform/CCGLView.h" #include "platform/CCGLView.h"
#include "base/CCDirector.h" #include "base/CCDirector.h"
#include "base/CCScheduler.h"
#include "platform/CCFileUtils.h" #include "platform/CCFileUtils.h"
#include "ui/UIHelper.h" #include "ui/UIHelper.h"
#include <mutex>
#include <condition_variable>
#define CLASS_NAME "org/cocos2dx/lib/Cocos2dxWebViewHelper" #define CLASS_NAME "org/cocos2dx/lib/Cocos2dxWebViewHelper"
@ -45,7 +48,7 @@
static const std::string s_defaultBaseUrl = "file:///android_asset/"; static const std::string s_defaultBaseUrl = "file:///android_asset/";
static const std::string s_sdRootBaseUrl = "file://"; static const std::string s_sdRootBaseUrl = "file://";
static std::string getFixedBaseUrl(const std::string& baseUrl) static std::string getFixedBaseUrl(const std::string& baseUrl)
{ {
std::string fixedBaseUrl; std::string fixedBaseUrl;
if (baseUrl.empty()) if (baseUrl.empty())
@ -401,45 +404,73 @@ namespace cocos2d {
setScalesPageToFitJNI(_viewTag, scalesPageToFit); setScalesPageToFitJNI(_viewTag, scalesPageToFit);
} }
// executed from Java's thread (we should invoke callback on cocos thread)
bool WebViewImpl::shouldStartLoading(const int viewTag, const std::string &url) { bool WebViewImpl::shouldStartLoading(const int viewTag, const std::string &url) {
auto it = s_WebViewImpls.find(viewTag);
if (it != s_WebViewImpls.end()) { std::mutex m;
auto webView = s_WebViewImpls[viewTag]->_webView; std::condition_variable cv;
if (webView->_onShouldStartLoading) { bool finished = false;
return webView->_onShouldStartLoading(webView, url); bool allowLoad = true;
Director::getInstance()->getScheduler()->performFunctionInCocosThread([&]{
auto it = s_WebViewImpls.find(viewTag);
if (it != s_WebViewImpls.end()) {
auto webView = s_WebViewImpls[viewTag]->_webView;
if (webView->_onShouldStartLoading) {
allowLoad = webView->_onShouldStartLoading(webView, url);
}
} }
}
return true; m.lock();
finished = true;
m.unlock();
cv.notify_one();
});
// wait for result from cocos thread
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, [&finished]{ return finished; });
return allowLoad;
} }
// executed from Java's thread (we should invoke callback on cocos thread)
void WebViewImpl::didFinishLoading(const int viewTag, const std::string &url){ void WebViewImpl::didFinishLoading(const int viewTag, const std::string &url){
auto it = s_WebViewImpls.find(viewTag); Director::getInstance()->getScheduler()->performFunctionInCocosThread([viewTag, url]{
if (it != s_WebViewImpls.end()) { auto it = s_WebViewImpls.find(viewTag);
auto webView = s_WebViewImpls[viewTag]->_webView; if (it != s_WebViewImpls.end()) {
if (webView->_onDidFinishLoading) { auto webView = s_WebViewImpls[viewTag]->_webView;
webView->_onDidFinishLoading(webView, url); if (webView->_onDidFinishLoading) {
webView->_onDidFinishLoading(webView, url);
}
} }
} });
} }
// executed from Java's thread (we should invoke callback on cocos thread)
void WebViewImpl::didFailLoading(const int viewTag, const std::string &url){ void WebViewImpl::didFailLoading(const int viewTag, const std::string &url){
auto it = s_WebViewImpls.find(viewTag); Director::getInstance()->getScheduler()->performFunctionInCocosThread([viewTag, url]{
if (it != s_WebViewImpls.end()) { auto it = s_WebViewImpls.find(viewTag);
auto webView = s_WebViewImpls[viewTag]->_webView; if (it != s_WebViewImpls.end()) {
if (webView->_onDidFailLoading) { auto webView = s_WebViewImpls[viewTag]->_webView;
webView->_onDidFailLoading(webView, url); if (webView->_onDidFailLoading) {
webView->_onDidFailLoading(webView, url);
}
} }
} });
} }
// executed from Java's thread (we should invoke callback on cocos thread)
void WebViewImpl::onJsCallback(const int viewTag, const std::string &message){ void WebViewImpl::onJsCallback(const int viewTag, const std::string &message){
auto it = s_WebViewImpls.find(viewTag); Director::getInstance()->getScheduler()->performFunctionInCocosThread([viewTag, message]{
if (it != s_WebViewImpls.end()) { auto it = s_WebViewImpls.find(viewTag);
auto webView = s_WebViewImpls[viewTag]->_webView; if (it != s_WebViewImpls.end()) {
if (webView->_onJSCallback) { auto webView = s_WebViewImpls[viewTag]->_webView;
webView->_onJSCallback(webView, message); if (webView->_onJSCallback) {
webView->_onJSCallback(webView, message);
}
} }
} });
} }
void WebViewImpl::draw(cocos2d::Renderer *renderer, cocos2d::Mat4 const &transform, uint32_t flags) { void WebViewImpl::draw(cocos2d::Renderer *renderer, cocos2d::Mat4 const &transform, uint32_t flags) {