diff --git a/lib/main.js b/lib/main.js index 08b74d30..82ca97e9 100755 --- a/lib/main.js +++ b/lib/main.js @@ -26,15 +26,17 @@ try { loadDefaultChimera(); } -setInterval(webkit.processEvents, 50); - var exports = module.exports; -var timer; -var processingEvents = true; +var timer = 0; +var processingEvents = false; +var referenceCount = 0; function stop() { - processingEvents = false; - clearInterval(timer); + --referenceCount; + if (referenceCount === 0) { + processingEvents = false; + clearInterval(timer); + } }; function start() { @@ -42,6 +44,7 @@ function start() { processingEvents = true; timer = setInterval(webkit.processEvents, 50); } + ++referenceCount; }; function Chimera(options) { @@ -51,14 +54,7 @@ function Chimera(options) { var cookies = options.cookies || ''; var disableImages = !!(options.disableImages); var shouldStart = false; - if (processingEvents) { - shouldStart = true; - // stop(); - } this.browser = new webkit.Browser(userAgent, libraryCode, cookies, disableImages); - if (shouldStart) { - // start(); - } var proxy = options.proxy; if (proxy) { this.setProxy(proxy.type, proxy.host, proxy.port, proxy.username, proxy.password) @@ -112,8 +108,10 @@ Chimera.prototype.perform = function(options) { var locals = options.locals || {}; var run = 'with('+JSON.stringify(locals)+'){(' + (options.run || function(callback) {callback(null, "");}) + ')(function(err,res) {window.chimera.callback(JSON.stringify(err), JSON.stringify(res));})}'; var callback = options.callback || function(err, result) {}; + start(); this.browser.open(url, run, function(errStr, resStr) { callback(parseOrReturn(errStr), parseOrReturn(resStr)); + stop(); }); } diff --git a/src/browser.cc b/src/browser.cc index 4f9d5593..42a83f6c 100644 --- a/src/browser.cc +++ b/src/browser.cc @@ -12,10 +12,9 @@ Browser::Browser(QString userAgent, QString libraryCode, QString cookies, bool d libraryCode_ = libraryCode; cookies_ = cookies; disableImages_ = disableImages; - chimera_ = 0; } + Browser::~Browser() { - delete chimera_; } void Browser::Initialize(Handle target) { @@ -51,8 +50,6 @@ Handle Browser::New(const Arguments& args) { void AsyncWork(uv_work_t* req) { BWork* work = static_cast(req->data); work->chimera->wait(); - work->result = work->chimera->getResult(); - work->errorResult = work->chimera->getError(); } void AsyncAfter(uv_work_t* req) { @@ -71,6 +68,9 @@ void AsyncAfter(uv_work_t* req) { node::FatalException(try_catch); } } else { + work->result = work->chimera->getResult(); + work->errorResult = work->chimera->getError(); + const unsigned argc = 2; Local argv[argc] = { Local::New(Null()), @@ -84,11 +84,8 @@ void AsyncAfter(uv_work_t* req) { } } - uv_queue_work(uv_default_loop(), &work->request, AsyncWork, AsyncAfter); - - // TODO: we need to figure out where to dispose the callback & free up work - // work->callback.Dispose(); - // delete work; + work->callback.Dispose(); + delete work; } Handle Browser::Cookies(const Arguments& args) { @@ -167,11 +164,10 @@ Handle Browser::Close(const Arguments& args) { Browser* w = ObjectWrap::Unwrap(args.This()); Chimera* chimera = w->getChimera(); - - if (0 != chimera) { + + if (NULL != chimera) { chimera->exit(1); - w->setChimera(0); - chimera->deleteLater(); + w->setChimera(NULL); } return scope.Close(Undefined()); diff --git a/src/browser.h b/src/browser.h index 736c1693..fcc7f5e0 100644 --- a/src/browser.h +++ b/src/browser.h @@ -1,6 +1,8 @@ #ifndef BROWSER_H #define BROWSER_H +#include + #include #include #include @@ -21,8 +23,8 @@ struct BWork { class Browser : public node::ObjectWrap { public: static void Initialize(v8::Handle target); - Chimera* getChimera() const { return chimera_; }; - void setChimera(Chimera *chimera) { chimera_ = chimera; }; + Chimera* getChimera() const { return chimera_.get(); }; + void setChimera(Chimera *chimera) { chimera_.reset(chimera); }; QString userAgent() {return userAgent_; }; QString libraryCode() {return libraryCode_; }; @@ -40,7 +42,7 @@ class Browser : public node::ObjectWrap { static v8::Handle SetCookies(const v8::Arguments& args); static v8::Handle SetProxy(const v8::Arguments& args); - Chimera* chimera_; + std::tr1::shared_ptr chimera_; QString libraryCode_; QString userAgent_; QString cookies_; diff --git a/src/chimera.cc b/src/chimera.cc index 1c007bcc..8b25fa3d 100644 --- a/src/chimera.cc +++ b/src/chimera.cc @@ -159,9 +159,9 @@ void Chimera::setEmbedScript(const QString &jscode) void Chimera::callback(const QString &errorResult, const QString &result) { + QMutexLocker locker(&m_mutex); m_errors.enqueue(errorResult); m_results.enqueue(result); - m_mutex.unlock(); m_loading.wakeAll(); } @@ -174,13 +174,15 @@ void Chimera::exit(int code) { m_page.triggerAction(QWebPage::Stop); m_returnValue = code; + QMutexLocker locker(&m_mutex); + m_loading.wakeAll(); + locker.unlock(); disconnect(&m_page, SIGNAL(loadFinished(bool)), this, SLOT(finish(bool))); } void Chimera::execute() { std::cout << "debug -- about to lock" << std::endl; - m_mutex.tryLock(); std::cout << "debug -- about to evaluate" << std::endl; m_page.mainFrame()->evaluateJavaScript(m_script); std::cout << "debug -- done evaluating" << std::endl; @@ -207,17 +209,13 @@ void Chimera::open(const QString &address) { m_page.triggerAction(QWebPage::Stop); m_loadStatus = "loading"; - m_mutex.lock(); m_page.mainFrame()->setUrl(QUrl(address)); } void Chimera::wait() { - if (m_mutex.tryLock()) { - m_mutex.unlock(); - } else { + QMutexLocker locker(&m_mutex); m_loading.wait(&m_mutex); - } } bool Chimera::capture(const QString &fileName) @@ -259,11 +257,19 @@ int Chimera::returnValue() const QString Chimera::getResult() { + if (m_results.isEmpty()) { + // TODO may cause by Browser::Close + return ""; + } return m_results.dequeue(); } QString Chimera::getError() { + if (m_errors.isEmpty()) { + // TODO may cause by Browser::Close + return ""; + } return m_errors.dequeue(); }