void MonkeyBinding::Callback(const ValueList &args, SharedValue result) { SharedKObject event = args.at(1)->ToObject(); std::string url_value = event->Get("url")->ToString(); std::vector< std::pair< std::pair< VectorOfPatterns,VectorOfPatterns >,std::string> >::iterator iter = scripts.begin(); while(iter!=scripts.end()) { std::pair< std::pair< VectorOfPatterns,VectorOfPatterns >, std::string> e = (*iter++); VectorOfPatterns include = e.first.first; VectorOfPatterns exclude = e.first.second; if (Matches(exclude,url_value)) { continue; } if (Matches(include,url_value)) { // I got a castle in brooklyn, that's where i dwell try { SharedKMethod eval = event->Get("scope")->ToObject()->Get("window")->ToObject()->Get("eval")->ToMethod(); #ifdef DEBUG std::cout << ">>> loading user script for " << url_value << std::endl; #endif eval->Call(Value::NewString(e.second)); } catch (ValueException &ex) { Logger* logger = Logger::Get("Monkey"); SharedString ss = ex.DisplayString(); int line = -1; if (ex.GetValue()->IsObject() && ex.GetValue()->ToObject()->Get("line")->IsNumber()) { line = ex.GetValue()->ToObject()->Get("line")->ToInt(); } logger->Error( "Exception generated evaluating user script for %s " "(line %i): %s", url_value.c_str(), line, ss->c_str()); } catch (std::exception &ex) { Logger* logger = Logger::Get("Monkey"); logger->Error("Exception generated evaluating user script for %s, Exception: %s",url_value.c_str(),ex.what()); } } } }
HRESULT STDMETHODCALLTYPE ScriptEvaluator::evaluate(BSTR mimeType, BSTR sourceCode, int *context) { std::string type = BSTRToString(mimeType); std::string moduleName = GetModuleName(type); JSContextRef contextRef = reinterpret_cast<JSContextRef>(context); SharedKObject global = host->GetGlobalObject(); SharedValue moduleValue = global->Get(moduleName.c_str()); if (!moduleValue->IsNull()) { SharedValue evalValue = moduleValue->ToObject()->Get("evaluate"); if (!evalValue->IsNull() && evalValue->IsMethod()) { ValueList args; SharedValue typeValue = Value::NewString(type); SharedValue sourceCodeValue = Value::NewString(BSTRToString(sourceCode)); JSObjectRef globalObjectRef = JSContextGetGlobalObject(contextRef); SharedKObject contextObject = new KKJSObject(contextRef, globalObjectRef); SharedValue contextValue = Value::NewObject(contextObject); args.push_back(typeValue); args.push_back(sourceCodeValue); args.push_back(contextValue); evalValue->ToMethod()->Call(args); } } return S_OK; }
void AppBinding::CreateProperties(const ValueList& args, SharedValue result) { AutoPtr<PropertiesBinding> properties = new PropertiesBinding(); result->SetObject(properties); if (args.size() > 0 && args.at(0)->IsObject()) { SharedKObject p = args.at(0)->ToObject(); SharedStringList names = p->GetPropertyNames(); for (size_t i = 0; i < names->size(); i++) { SharedValue value = p->Get(names->at(i)); ValueList setterArgs; setterArgs.push_back(Value::NewString(names->at(i))); setterArgs.push_back(value); PropertiesBinding::Type type; if (value->IsList()) type = PropertiesBinding::List; else if (value->IsInt()) type = PropertiesBinding::Int; else if (value->IsDouble()) type = PropertiesBinding::Double; else if (value->IsBool()) type = PropertiesBinding::Bool; else type = PropertiesBinding::String; properties->Setter(setterArgs, type); } } }
void HTTPClientBinding::SendFile(const ValueList& args, SharedValue result) { if (this->Get("connected")->ToBool()) { throw ValueException::FromString("already connected"); } if (args.size()==1) { // can be a string of data or a file SharedValue v = args.at(0); if (v->IsObject()) { // probably a file SharedKObject obj = v->ToObject(); if (obj->Get("isFile")->IsMethod()) { std::string file = obj->Get("toString")->ToMethod()->Call()->ToString(); this->filestream = new Poco::FileInputStream(file); Poco::Path p(file); this->filename = p.getFileName(); } else { this->datastream = obj->Get("toString")->ToMethod()->Call()->ToString(); } } else if (v->IsString()) { this->filestream = new Poco::FileInputStream(v->ToString()); } else { throw ValueException::FromString("unknown data type"); } } this->thread = new Poco::Thread(); this->thread->start(&HTTPClientBinding::Run,(void*)this); if (!this->async) { PRINTD("Waiting on HTTP Client thread to finish"); this->thread->join(); } }
void MonkeyBinding::EvaluateUserScript( SharedKObject event, std::string& url, SharedKObject windowObject, std::string& scriptSource) { static Logger *logger = Logger::Get("Monkey"); // I got a castle in brooklyn, that's where i dwell // Word, brother. if (!windowObject->Get("eval")->IsMethod()) { logger->Error("Found a window object without an " "eval function (%s) -- aborting", url.c_str()); return; } SharedKObject target = event->GetObject("target"); if (!windowObject->Get(GLOBAL_NS_VARNAME)->IsObject() && !target.isNull() && target->Get("insertAPI")->IsMethod()) { logger->Info("Forcing Titanium API into: %s\n", url.c_str()); target->CallNS("insertAPI", Value::NewObject(windowObject)); } SharedKMethod evalFunction = windowObject->GetMethod("eval"); logger->Info("Loading userscript for %s\n", url.c_str()); try { evalFunction->Call(Value::NewString(scriptSource)); } catch (ValueException &ex) { SharedString ss = ex.DisplayString(); int line = -1; if (ex.GetValue()->IsObject() && ex.GetValue()->ToObject()->Get("line")->IsNumber()) { line = ex.GetValue()->ToObject()->Get("line")->ToInt(); } logger->Error( "Exception generated evaluating user script for %s " "(line %i): %s", url.c_str(), line, ss->c_str()); } }
// A :responds_to? method for finding KObject properties in Ruby static VALUE RubyKObjectRespondTo(int argc, VALUE *argv, VALUE self) { SharedValue* dval = NULL; Data_Get_Struct(self, SharedValue, dval); SharedKObject object = (*dval)->ToObject(); VALUE mid, priv; // We ignore the priv argument rb_scan_args(argc, argv, "11", &mid, &priv); const char* name = rb_id2name(rb_to_id(mid)); SharedValue value = object->Get(name); return value->IsUndefined() ? Qfalse : Qtrue; }
void MonkeyBinding::Callback(const ValueList &args, SharedValue result) { SharedKObject event = args.at(0)->ToObject(); if (!event->Get("url")->IsString() || !event->Get("scope")->IsObject() || !event->GetObject("scope")->Get("window")) { throw ValueException::FromString( "ti.Monkey could not find required components of PAGE_LOADED events"); } std::string url = event->GetString("url"); SharedKObject windowObject = event->GetObject("scope")->GetObject("window"); vector<Script*>::iterator iter = scripts.begin(); while (iter != scripts.end()) { Script* script = (*iter++); if (script->Matches(url)) { EvaluateUserScript(event, url, windowObject, script->source); } } }
// A :method_missing method for finding KObject properties in Ruby static VALUE RubyKObjectMethodMissing(int argc, VALUE *argv, VALUE self) { SharedValue* dval = NULL; Data_Get_Struct(self, SharedValue, dval); SharedKObject object = (*dval)->ToObject(); // TODO: We should raise an exception instead if (object.isNull()) return Qnil; // This is the same error that ruby throws if (argc == 0 || !SYMBOL_P(argv[0])) { rb_raise(rb_eArgError, "no id given"); } // We need to determine the method that was invoked: // store the method name and arguments in separate variables VALUE r_name, args; rb_scan_args(argc, argv, "1*", &r_name, &args); const char* name = rb_id2name(SYM2ID(r_name)); // Check if this is an assignment SharedValue value = object->Get(name); if (name[strlen(name) - 1] == '=' && argc > 1) { char* mod_name = strdup(name); mod_name[strlen(mod_name) - 1] = '\0'; value = RubyUtils::ToKrollValue(argv[1]); object->Set(mod_name, value); free(mod_name); return argv[1]; } else if (value->IsUndefined()) // raise a method missing error { VALUE selfString = rb_obj_as_string(self); rb_raise(rb_eNoMethodError, "undefined method `%s' for %s", name, RubyUtils::ToString(selfString)); } else if (value->IsMethod()) // actually call a method { return RubyUtils::GenericKMethodCall(value->ToMethod(), args); } else // Plain old access { return RubyUtils::ToRubyValue(value); } }
HRESULT STDMETHODCALLTYPE ScriptEvaluator::matchesMimeType(BSTR mimeType, BOOL *result) { std::string moduleName = GetModuleName(BSTRToString(mimeType)); SharedKObject global = host->GetGlobalObject(); SharedValue moduleValue = global->Get(moduleName.c_str()); *result = FALSE; if (!moduleValue->IsNull() && moduleValue->IsObject()) { if (!moduleValue->ToObject()->Get("evaluate")->IsNull() && !moduleValue->ToObject()->Get("evaluate")->IsUndefined() && moduleValue->ToObject()->Get("evaluate")->IsMethod()) { *result = TRUE; } } return S_OK; }
void HTTPClientBinding::Send(const ValueList& args, SharedValue result) { if (this->Get("connected")->ToBool()) { throw ValueException::FromString("already connected"); } if (args.size()==1) { // can be a string of data or a file SharedValue v = args.at(0); if (v->IsObject()) { // probably a file SharedKObject obj = v->ToObject(); this->datastream = obj->Get("toString")->ToMethod()->Call()->ToString(); } else if (v->IsString()) { this->datastream = v->ToString(); } else if (v->IsNull() || v->IsUndefined()) { this->datastream = ""; } else { throw ValueException::FromString("unknown data type"); } } this->thread = new Poco::Thread(); this->thread->start(&HTTPClientBinding::Run,(void*)this); if (!this->async) { PRINTD("Waiting on HTTP Client thread to finish (sync)"); Poco::Stopwatch sw; sw.start(); while (!this->shutdown && sw.elapsedSeconds() * 1000 < this->timeout) { this->thread->tryJoin(100); } PRINTD("HTTP Client thread finished (sync)"); } }
void NetworkBinding::GetHostByAddress(const ValueList& args, SharedValue result) { if (args.at(0)->IsObject()) { SharedKObject obj = args.at(0)->ToObject(); SharedPtr<IPAddressBinding> b = obj.cast<IPAddressBinding>(); if (!b.isNull()) { // in this case, they've passed us an IPAddressBinding // object, which we can just retrieve the ipaddress // instance and resolving using it IPAddress addr(b->GetAddress()->toString()); SharedPtr<HostBinding> binding = new HostBinding(addr); if (binding->IsInvalid()) { throw ValueException::FromString("Could not resolve address"); } result->SetObject(binding); return; } else { SharedValue bo = obj->Get("toString"); if (bo->IsMethod()) { SharedKMethod m = bo->ToMethod(); ValueList args; SharedValue tostr = m->Call(args); this->_GetByHost(tostr->ToString(),result); return; } throw ValueException::FromString("Unknown object passed"); } } else if (args.at(0)->IsString()) { // in this case, they just passed in a string so resolve as // normal this->_GetByHost(args.at(0)->ToString(),result); } }
// A :method method for pulling methods off of KObjects in Ruby static VALUE RubyKObjectMethod(int argc, VALUE *argv, VALUE self) { SharedValue* dval = NULL; Data_Get_Struct(self, SharedValue, dval); SharedKObject object = (*dval)->ToObject(); // TODO: We should raise an exception instead if (object.isNull()) return Qnil; if (argc < 1) return Qnil; VALUE meth_name = argv[0]; const char* name = rb_id2name(SYM2ID(meth_name)); SharedValue v = object->Get(name); if (v->IsMethod()) { return RubyUtils::ToRubyValue(v); } else { return Qnil; } }
void UserWindow::_SetBounds(const kroll::ValueList& args, kroll::SharedValue result) { if (args.size() < 1 || !args.at(0)->IsObject()) { throw ValueException::FromString("setBounds takes an object with x, y, width and height properties."); return; } SharedKObject o = args.at(0)->ToObject(); if (!o->Get("x")->IsNumber() || !o->Get("y")->IsNumber() || !o->Get("width")->IsNumber() ||!o->Get("height")->IsNumber()) { throw ValueException::FromString("setBounds takes an object with x, y, width and height properties."); return; } double x = o->Get("x")->ToNumber(); double y = o->Get("y")->ToNumber(); double w = o->Get("width")->ToNumber(); double h = o->Get("height")->ToNumber(); w = UserWindow::Constrain(w, config->GetMinWidth(), config->GetMaxWidth()); h = UserWindow::Constrain(h, config->GetMinHeight(), config->GetMaxHeight()); this->config->SetX(x); this->config->SetY(y); this->config->SetWidth(w); this->config->SetHeight(h); if (this->active) { Bounds bounds; bounds.x = x; bounds.y = y; bounds.width = w; bounds.height = h; this->SetBounds(bounds); } }
void GtkUserWindow::Open() { if (this->gtk_window == NULL) { WebKitWebView* web_view = WEBKIT_WEB_VIEW (webkit_web_view_new ()); g_signal_connect( G_OBJECT(web_view), "window-object-cleared", G_CALLBACK(window_object_cleared_cb), this); g_signal_connect( G_OBJECT(web_view), "navigation-requested", G_CALLBACK(navigation_requested_cb), this); g_signal_connect( G_OBJECT(web_view), "new-window-navigation-requested", G_CALLBACK(new_window_navigation_requested_cb), this); g_signal_connect( G_OBJECT(web_view), "populate-popup", G_CALLBACK(populate_popup_cb), this); g_signal_connect( G_OBJECT(web_view), "load-finished", G_CALLBACK(load_finished_cb), this); // Tell Titanium what Webkit is using for a user-agent SharedKObject global = host->GetGlobalObject(); if (global->Get("userAgent")->IsUndefined()) { gchar* user_agent = webkit_web_view_get_user_agent(G_OBJECT(web_view)); global->Set("userAgent", Value::NewString(user_agent)); g_free(user_agent); } WebKitWebSettings* settings = webkit_web_settings_new(); g_object_set(G_OBJECT(settings), "enable-developer-extras", TRUE, NULL); webkit_web_view_set_settings(WEBKIT_WEB_VIEW(web_view), settings); GtkWidget* view_container = NULL; if (this->IsUsingScrollbars()) { /* web view scroller */ GtkWidget* scrolled_window = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_container_add( GTK_CONTAINER (scrolled_window), GTK_WIDGET (web_view)); view_container = scrolled_window; } else // No scrollin' fer ya. { view_container = GTK_WIDGET(web_view); } /* main window vbox */ this->vbox = gtk_vbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX (vbox), GTK_WIDGET(view_container), TRUE, TRUE, 0); /* main window */ GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_widget_set_name(window, this->config->GetTitle().c_str()); gtk_window_set_title(GTK_WINDOW(window), this->config->GetTitle().c_str()); this->destroy_cb_id = g_signal_connect( G_OBJECT(window), "destroy", G_CALLBACK(destroy_cb), this); g_signal_connect(G_OBJECT(window), "event", G_CALLBACK(event_cb), this); gtk_container_add(GTK_CONTAINER (window), vbox); webkit_web_view_register_url_scheme_as_local("app"); webkit_web_view_register_url_scheme_as_local("ti"); this->gtk_window = GTK_WINDOW(window); this->web_view = web_view; //this->SetupTransparency(); gtk_widget_realize(window); this->SetupDecorations(); this->SetupSize(); this->SetupSizeLimits(); this->SetupPosition(); this->SetupMenu(); this->SetupIcon(); this->SetTopMost(config->IsTopMost()); this->SetCloseable(config->IsCloseable()); gtk_widget_grab_focus(GTK_WIDGET (web_view)); webkit_web_view_open(web_view, this->config->GetURL().c_str()); if (this->IsVisible()) { gtk_widget_show_all(window); } if (this->config->IsFullScreen()) { gtk_window_fullscreen(this->gtk_window); } UserWindow::Open(); this->FireEvent(OPENED); } else { this->Show(); } }