void TCPSocketBinding::ReadyForRead( const Poco::AutoPtr<Poco::Net::ReadableNotification>& n) { static std::string eprefix("TCPSocketBinding::OnRead: "); try { // Always read bytes, so that the tubes get cleared. char data[BUFFER_SIZE + 1]; int size = socket.receiveBytes(&data, BUFFER_SIZE); // A read is only complete if we've already read some bytes from the socket. bool readComplete = this->readStarted && (size <= 0); this->readStarted = (size > 0); if (readComplete && !this->onReadComplete.isNull()) { ValueList args; RunOnMainThread(this->onReadComplete, args, false); } else if (size > 0 && !this->onRead.isNull()) { data[size] = '\0'; BlobRef blob(new Blob(data, size)); ValueList args(Value::NewObject(blob)); RunOnMainThread(this->onRead, args, false); } } catch (ValueException& e) { GetLogger()->Error("Read failed: %s", e.ToString().c_str()); ValueList args(Value::NewString(e.ToString())); if (!this->onError.isNull()) RunOnMainThread(this->onError, args, false); } catch (Poco::Exception &e) { GetLogger()->Error("Read failed: %s", e.displayText().c_str()); ValueList args(Value::NewString(e.displayText())); if (!this->onError.isNull()) RunOnMainThread(this->onError, args, false); } catch (...) { GetLogger()->Error("Read failed: unknown exception"); ValueList args(Value::NewString("Unknown exception during read")); if (!this->onError.isNull()) RunOnMainThread(this->onError, args, false); } }
bool EventListener::Dispatch(KObjectRef thisObject, const ValueList& args, bool synchronous) { KValueRef result = RunOnMainThread(this->callback, thisObject, args, synchronous); if (result->IsBool()) return result->ToBool(); return true; }
void UIBinding::Log(Logger::Level level, std::string& message) { if (level > Logger::LWARN) return; std::string methodName("warn"); if (level < Logger::LWARN) methodName = "error"; std::string origMethodName(methodName); origMethodName.append("_orig"); std::vector<AutoUserWindow>& openWindows = UIBinding::GetInstance()->GetOpenWindows(); for (size_t i = 0; i < openWindows.size(); i++) { KObjectRef domWindow = openWindows[i]->GetDOMWindow(); if (domWindow.isNull()) continue; KObjectRef console = domWindow->GetObject("console", 0); if (console.isNull()) continue; KMethodRef method = console->GetMethod(origMethodName.c_str(), 0); if (method.isNull()) method = console->GetMethod(methodName.c_str(), 0); RunOnMainThread(method, ValueList(Value::NewString(message)), false); } }
/*static*/ KValueRef Codec::ExtractZipAsync(const ValueList& args) { std::string zipFile = args.GetString(0); std::string directory = args.GetString(1); AutoPtr<AsyncJob> job = args.GetObject(2).cast<AsyncJob>(); KMethodRef callback = 0; if (args.size() > 3) { callback = args.GetMethod(3); } std::ifstream stream(UTF8ToSystem(zipFile).c_str(), std::ios::binary); Poco::Zip::Decompress decompressor(stream, directory); try { decompressor.decompressAllFiles(); } catch (std::exception& e) { Logger::Get("Codec")->Error("exception decompressing: %s", e.what()); throw ValueException::FromFormat("Exception during extraction: %s", e.what()); } stream.close(); if (!callback.isNull()) { ValueList args; args.push_back(Value::NewString(directory)); RunOnMainThread(callback, args, true); } return Value::Undefined; }
void TCPSocketBinding::ConnectThread() { static std::string error("Connection failed: "); try { // Give the connetion process and the reactor the same timeout. this->socket.connect(Poco::Net::SocketAddress( this->host, this->port), this->timeout); // Enable Keepalive mode on this socket. See: // http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/index.html this->socket.setKeepAlive(true); this->reactor.setTimeout(this->timeout); this->thread.start(this->reactor); this->opened = true; return; } catch (Poco::IOException &e) { error.append(e.displayText()); } catch (std::exception &e) { error.append(e.what()); } catch (...) { error.append("Unknown exception"); } if (!this->onError.isNull()) RunOnMainThread(this->onError, ValueList(Value::NewString(error)), false); }
bool NetworkStatus::GetStatus() { if (!bus) return true; return RunOnMainThread(statusCheckWork, ValueList())->ToBool(); }
void HTTPRequestHandler::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response) { // XXX(Josh): The request and response object's lifetime is limited to this functions call. // If the developer should keep a reference to these around past the callback lifetime and then // attempts to access it may result in a crash! ValueList args; args.push_back(Value::NewObject(new HttpServerRequest(request))); args.push_back(Value::NewObject(new HttpServerResponse(response))); RunOnMainThread(m_callback, args); }
void TCPServerConnectionBinding::onErrored(const Poco::AutoPtr<Poco::Net::ErrorNotification>& notification) { if (this->onError.isNull()) { return; } ValueList args(Value::NewString(notification->name())); RunOnMainThread(this->onError, args, false); }
void TCPSocketBinding::OnTimeout( const Poco::AutoPtr<Poco::Net::TimeoutNotification>& n) { if (this->onTimeout.isNull()) { return; } RunOnMainThread(this->onTimeout, ValueList(), false); }
void TCPSocketBinding::OnError( const Poco::AutoPtr<Poco::Net::ErrorNotification>& n) { if (this->onError.isNull()) { return; } ValueList args(Value::NewString(n->name())); RunOnMainThread(this->onError, args, false); }
void MenuItem::HandleClickEvent(KObjectRef source) { if (this->FireEvent(Event::CLICKED) && this->IsCheck() && this->autoCheck) { // Execute this later on the main thread RunOnMainThread(this->Get("setState")->ToMethod(), ValueList(Value::NewBool(!this->GetState())), false); } }
void Process::ExitMonitorSync() { this->exitCode = Value::NewInt(this->Wait()); this->GetNativeStdin()->StopMonitors(); this->GetNativeStdout()->StopMonitors(); this->GetNativeStderr()->StopMonitors(); if (!exitCallback.isNull()) RunOnMainThread(exitCallback, ValueList()); }
bool GMPTimerChild::RecvTimerExpired(const uint32_t& aTimerId) { MOZ_ASSERT(mPlugin->GMPMessageLoop() == MessageLoop::current()); GMPTask* task = mTimers.Get(aTimerId); mTimers.Remove(aTimerId); if (task) { RunOnMainThread(task); } return true; }
void ZipFile::notifyDecompressComplete(bool ret, const std::string & err) const { if (this->onDecompressCompleteCallback) { ValueList cb_args; cb_args.push_back(Value::NewBool(ret)); if (!ret) { cb_args.push_back(Value::NewString(err)); } RunOnMainThread(this->onDecompressCompleteCallback, cb_args, false); } }
void Done(GMPTask* aToRun, GMPTask* aToDestroy) { // Note: Call Close() before running continuation, in case the // continuation tries to open the same record; if we call Close() // after running the continuation, the Close() call will arrive // just after the Open() call succeeds, immediately closing the // record we just opened. if (mRecord) { mRecord->Close(); } aToDestroy->Destroy(); RunOnMainThread(aToRun); delete this; }
void APIBinding::RunInstaller() { START_KROLL_THREAD; SharedApplication app = host->GetApplication(); BootUtils::RunInstaller( this->installerDependencies, app, "", app->GetSDKPath(), true); if (!this->installerCallback.isNull()) { RunOnMainThread(this->installerCallback, ValueList(), false); } this->installerMutex.unlock(); END_KROLL_THREAD; }
static void FireEventCallback(KMethodRef callback, AutoPtr<Event> event, bool synchronous, KObjectRef thisObject) { try { RunOnMainThread(callback, thisObject, ValueList(Value::NewObject(event)), synchronous); } catch (ValueException& e) { Logger* logger = Logger::Get("KEventObject"); SharedString ss = e.DisplayString(); logger->Error("Exception caught during event callback (target=[%s]): %s", event->target->GetType().c_str(), ss->c_str()); } }
void TCPServerConnectionBinding::onWritable (const Poco::AutoPtr<Poco::Net::WritableNotification>& notification) { if (this->closed) { return; } if (sendData.empty()) { this->reactor.removeEventHandler(socket, Poco::NObserver<TCPServerConnectionBinding, Poco::Net::WritableNotification>(*this, &TCPServerConnectionBinding::onWritable)); writeReadyHandlerInstalled = false; return; } BytesRef buffer(0); { Poco::Mutex::ScopedLock lock(sendDataMutex); buffer = sendData.front(); } const char* data = buffer->Pointer() + currentSendDataOffset; size_t length = buffer->Length() - currentSendDataOffset; size_t count = this->socket.sendBytes(data, length); currentSendDataOffset += count; if (currentSendDataOffset == (size_t) buffer->Length()) { // Only send the onWrite message when we've exhausted a Bytes. if (!this->onWrite.isNull()) { ValueList args(Value::NewInt(buffer->Length())); RunOnMainThread(this->onWrite, args, false); } Poco::Mutex::ScopedLock lock(sendDataMutex); sendData.pop(); currentSendDataOffset = 0; // Uninstall the ReadyForWrite reactor handler, because it will push // the CPU to 100% usage if there is nothing to write. if (sendData.size() == 0) { this->reactor.removeEventHandler(socket, Poco::NObserver<TCPServerConnectionBinding, Poco::Net::WritableNotification>(*this, &TCPServerConnectionBinding::onWritable)); writeReadyHandlerInstalled = false; } } }
void WorkerContext::CallOnMessageCallback(KMethodRef onMessage, KValueRef message) { static Logger* logger = Logger::Get("Worker"); AutoPtr<Event> event(this->CreateEvent("worker.message")); event->Set("message", message); ValueList args(Value::NewObject(event)); try { RunOnMainThread(onMessage, args, false); } catch(ValueException& e) { logger->Error("Exception while during onMessage callback: %s", e.ToString().c_str()); } }
void APIBinding::_RunOnMainThreadAsync(const ValueList& args, KValueRef result) { if (!args.at(0)->IsMethod()) { throw ValueException::FromString( "First argument to runOnMainThread was not a function"); } else { ValueList outArgs; for (size_t i = 1; i < args.size(); i++) outArgs.push_back(args.at(i)); RunOnMainThread(args.GetMethod(0), outArgs, false); } }
void Process::ExitMonitorAsync() { this->exitCode = Value::NewInt(this->Wait()); // We want the onRead callbacks to fire before the exit // event, so we do a little hack here and stop the event // threads on the native pipes. It shouldn't matter anyhow // because these pipes are now dead and will be replaced on // next launch. Don't do this for synchronous process // launch becauase we are already on the main thread and that // will cause a deadlock. this->GetNativeStdin()->StopMonitors(); this->GetNativeStdout()->StopMonitors(); this->GetNativeStderr()->StopMonitors(); if (!exitCallback.isNull()) RunOnMainThread(exitCallback, ValueList()); }
/*static*/ KValueRef Codec::CreateZipAsync(const ValueList& args) { std::string directory = args.GetString(0); std::string zipFile = args.GetString(1); AutoPtr<AsyncJob> job = args.GetObject(2).cast<AsyncJob>(); KMethodRef callback = 0; if (args.size() > 3) { callback = args.GetMethod(3); } Poco::Path path(directory); path.makeDirectory(); std::ofstream stream(UTF8ToSystem(zipFile).c_str(), std::ios::binary | std::ios::trunc); Poco::Zip::Compress compressor(stream, true); try { compressor.addRecursive(path); } catch (std::exception& e) { Logger::Get("Codec")->Error("exception compressing: %s", e.what()); throw ValueException::FromFormat("Exception during zip: %s", e.what()); } compressor.close(); stream.close(); if (!callback.isNull()) { ValueList args; args.push_back(Value::NewString(zipFile)); RunOnMainThread(callback, args, true); } return Value::Undefined; }
void Network::NetworkStatusChange(bool online) { static Logger* log = Logger::Get("NetworkStatus"); log->Debug("ti.Network: Online status changed ==> %i", online); this->Set("online", Value::NewBool(online)); ValueList args = ValueList(); args.push_back(Value::NewBool(online)); std::vector<Listener>::iterator it = this->listeners.begin(); while (it != this->listeners.end()) { KMethodRef callback = (*it++).callback; try { RunOnMainThread(callback, args, false); } catch(ValueException& e) { SharedString ss = e.GetValue()->DisplayString(); log->Error("Network.NetworkStatus callback failed: %s", ss->c_str()); } } }
void AsyncJob::DoCallback(KMethodRef method, bool reportErrors) { ValueList args(Value::NewObject(GetAutoPtr())); RunOnMainThread(method, args, false); }
void AsyncCopy::Run(void* data) { START_KROLL_THREAD; Logger* logger = Logger::Get("Filesystem.AsyncCopy"); AsyncCopy* ac = static_cast<AsyncCopy*>(data); std::vector<std::string>::iterator iter = ac->files.begin(); Poco::Path to(ac->destination); Poco::File tof(to.toString()); logger->Debug("Job started: dest=%s, count=%i", ac->destination.c_str(), ac->files.size()); if (!tof.exists()) { tof.createDirectory(); } int c = 0; while (!ac->stopped && iter!=ac->files.end()) { bool err_copy = false; std::string file = (*iter++); c++; logger->Debug("File: path=%s, count=%i\n", file.c_str(), c); try { Poco::Path from(file); Poco::File f(file); if (f.isDirectory()) { ac->Copy(from,to); } else { Poco::Path dest(to,from.getFileName()); ac->Copy(from,dest); } logger->Debug("File copied"); KValueRef value = Value::NewString(file); ValueList args; args.push_back(value); args.push_back(Value::NewInt(c)); args.push_back(Value::NewInt(ac->files.size())); args.push_back(Value::NewBool(true)); RunOnMainThread(ac->callback, args, false); logger->Debug("Callback executed"); } catch (ValueException &ex) { err_copy = true; SharedString ss = ex.DisplayString(); logger->Error(std::string("Error: ") + *ss + " for file: " + file); } catch (Poco::Exception &ex) { err_copy = true; logger->Error(std::string("Error: ") + ex.displayText() + " for file: " + file); } catch (std::exception &ex) { err_copy = true; logger->Error(std::string("Error: ") + ex.what() + " for file: " + file); } catch (...) { err_copy = true; logger->Error(std::string("Unknown error during copy: ") + file); } try { if(err_copy) { KValueRef value = Value::NewString(file); ValueList args; args.push_back(value); args.push_back(Value::NewInt(c)); args.push_back(Value::NewInt(ac->files.size())); args.push_back(Value::NewBool(false)); RunOnMainThread(ac->callback, args, false); } } catch(...) { err_copy = true; logger->Error(std::string("Unknown error during copy: ") + file); } } ac->Set("running",Value::NewBool(false)); ac->stopped = true; logger->Debug(std::string("Job finished")); END_KROLL_THREAD; }
void TCPServerConnectionBinding::onReadable (const Poco::AutoPtr<Poco::Net::ReadableNotification>& notification) { if (this->closed) { return; } static std::string eprefix("TCPServerConnectionBinding::OnRead: "); try { // Always read bytes, so that the tubes get cleared. char data[BUFFER_SIZE + 1]; int size = socket.receiveBytes(&data, BUFFER_SIZE); // A read is only complete if we've already read some bytes from the socket. bool readComplete = this->readStarted && (size <= 0); this->readStarted = (size > 0); if (readComplete && !this->onReadComplete.isNull()) { ValueList args; RunOnMainThread(this->onReadComplete, args, false); } else if (size > 0 && !this->onRead.isNull()) { data[size] = '\0'; BytesRef bytes(new Bytes(data, size)); ValueList args(Value::NewObject(bytes)); RunOnMainThread(this->onRead, args, false); } } catch (ValueException& e) { GetLogger()->Error("Read failed: %s", e.ToString().c_str()); ValueList args(Value::NewString(e.ToString())); if (!this->onError.isNull()) RunOnMainThread(this->onError, args, false); } catch (Poco::Exception &e) { // sometimes we'll get a I/O error (9) after closing during // a read, we can safely ignore errors if closed if (!this->closed) { GetLogger()->Error("Read failed: %s", e.displayText().c_str()); ValueList args(Value::NewString(e.displayText())); if (!this->onError.isNull()) RunOnMainThread(this->onError, args, false); } } catch (...) { GetLogger()->Error("Read failed: unknown exception"); ValueList args(Value::NewString("Unknown exception during read")); if (!this->onError.isNull()) RunOnMainThread(this->onError, args, false); } }