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 "platform/CCGLView.h"
#include "base/CCDirector.h"
#include "base/CCScheduler.h"
#include "platform/CCFileUtils.h"
#include "ui/UIHelper.h"
#include <mutex>
#include <condition_variable>
#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_sdRootBaseUrl = "file://";
static std::string getFixedBaseUrl(const std::string& baseUrl)
static std::string getFixedBaseUrl(const std::string& baseUrl)
{
std::string fixedBaseUrl;
if (baseUrl.empty())
@ -401,45 +404,73 @@ namespace cocos2d {
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) {
auto it = s_WebViewImpls.find(viewTag);
if (it != s_WebViewImpls.end()) {
auto webView = s_WebViewImpls[viewTag]->_webView;
if (webView->_onShouldStartLoading) {
return webView->_onShouldStartLoading(webView, url);
std::mutex m;
std::condition_variable cv;
bool finished = false;
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){
auto it = s_WebViewImpls.find(viewTag);
if (it != s_WebViewImpls.end()) {
auto webView = s_WebViewImpls[viewTag]->_webView;
if (webView->_onDidFinishLoading) {
webView->_onDidFinishLoading(webView, url);
Director::getInstance()->getScheduler()->performFunctionInCocosThread([viewTag, url]{
auto it = s_WebViewImpls.find(viewTag);
if (it != s_WebViewImpls.end()) {
auto webView = s_WebViewImpls[viewTag]->_webView;
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){
auto it = s_WebViewImpls.find(viewTag);
if (it != s_WebViewImpls.end()) {
auto webView = s_WebViewImpls[viewTag]->_webView;
if (webView->_onDidFailLoading) {
webView->_onDidFailLoading(webView, url);
Director::getInstance()->getScheduler()->performFunctionInCocosThread([viewTag, url]{
auto it = s_WebViewImpls.find(viewTag);
if (it != s_WebViewImpls.end()) {
auto webView = s_WebViewImpls[viewTag]->_webView;
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){
auto it = s_WebViewImpls.find(viewTag);
if (it != s_WebViewImpls.end()) {
auto webView = s_WebViewImpls[viewTag]->_webView;
if (webView->_onJSCallback) {
webView->_onJSCallback(webView, message);
Director::getInstance()->getScheduler()->performFunctionInCocosThread([viewTag, message]{
auto it = s_WebViewImpls.find(viewTag);
if (it != s_WebViewImpls.end()) {
auto webView = s_WebViewImpls[viewTag]->_webView;
if (webView->_onJSCallback) {
webView->_onJSCallback(webView, message);
}
}
}
});
}
void WebViewImpl::draw(cocos2d::Renderer *renderer, cocos2d::Mat4 const &transform, uint32_t flags) {