Index: jni/abpEngine.cpp |
=================================================================== |
new file mode 100644 |
--- /dev/null |
+++ b/jni/abpEngine.cpp |
@@ -0,0 +1,292 @@ |
+/* |
+ * This file is part of Adblock Plus <http://adblockplus.org/>, |
+ * Copyright (C) 2006-2013 Eyeo GmbH |
+ * |
+ * Adblock Plus is free software: you can redistribute it and/or modify |
+ * it under the terms of the GNU General Public License version 3 as |
+ * published by the Free Software Foundation. |
+ * |
+ * Adblock Plus is distributed in the hope that it will be useful, |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ * GNU General Public License for more details. |
+ * |
+ * You should have received a copy of the GNU General Public License |
+ * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. |
+ */ |
+ |
+#include <jni.h> |
+#include <AdblockPlus.h> |
+#include "AndroidLogSystem.h" |
+#include "AndroidWebRequest.h" |
+#include "Utils.h" |
+#include "debug.h" |
+ |
+JavaVM* globalJvm; |
+AdblockPlus::FilterEngine* filterEngine; |
Wladimir Palant
2013/09/12 11:31:14
Please use a smart pointer here, raw pointers shou
|
+jobject jniObject; |
+ |
+extern "C" |
+{ |
+ JNIEXPORT void JNICALL Java_org_adblockplus_android_ABPEngine_initialize(JNIEnv *pEnv, jobject, jstring basepath); |
+ JNIEXPORT void JNICALL Java_org_adblockplus_android_ABPEngine_release(JNIEnv *pEnv, jobject); |
+ JNIEXPORT jboolean JNICALL Java_org_adblockplus_android_ABPEngine_isFirstRun(JNIEnv *pEnv, jobject); |
+ JNIEXPORT jobjectArray JNICALL Java_org_adblockplus_android_ABPEngine_getListedSubscriptions(JNIEnv *pEnv, jobject); |
+ JNIEXPORT jobjectArray JNICALL Java_org_adblockplus_android_ABPEngine_getRecommendedSubscriptions(JNIEnv *pEnv, jobject); |
+ JNIEXPORT void JNICALL Java_org_adblockplus_android_ABPEngine_addSubscription(JNIEnv *pEnv, jobject, jstring url); |
+ JNIEXPORT void JNICALL Java_org_adblockplus_android_ABPEngine_removeSubscription(JNIEnv *pEnv, jobject, jstring url); |
+ JNIEXPORT void JNICALL Java_org_adblockplus_android_ABPEngine_refreshSubscription(JNIEnv *pEnv, jobject, jstring url); |
+ JNIEXPORT void JNICALL Java_org_adblockplus_android_ABPEngine_actualizeSubscriptionStatus(JNIEnv *pEnv, jobject, jstring url); |
+ JNIEXPORT jboolean JNICALL Java_org_adblockplus_android_ABPEngine_matches(JNIEnv *pEnv, jobject, jstring url, jstring contentType, jstring documentUrl); |
+ JNIEXPORT jobjectArray JNICALL Java_org_adblockplus_android_ABPEngine_getSelectorsForDomain(JNIEnv *pEnv, jobject, jstring domain); |
+}; |
+ |
+jobjectArray subscriptionsAsJavaArray(JNIEnv *pEnv, std::vector<AdblockPlus::SubscriptionPtr> subscriptions) |
+{ |
+ D(D_WARN, "subscriptionsAsJavaArray()"); |
+ static jclass cls = reinterpret_cast<jclass>(pEnv->NewGlobalRef(pEnv->FindClass("org/adblockplus/android/Subscription"))); |
+ static jmethodID cid = pEnv->GetMethodID(cls, "<init>", "()V"); |
+ static jfieldID ftitle = pEnv->GetFieldID(cls, "title", "Ljava/lang/String;"); |
+ static jfieldID furl = pEnv->GetFieldID(cls, "url", "Ljava/lang/String;"); |
+ |
+ D(D_WARN, "Subscriptions: %d", subscriptions.size()); |
+ const jobjectArray ret = (jobjectArray) pEnv->NewObjectArray(subscriptions.size(), cls, NULL); |
Wladimir Palant
2013/09/12 11:31:14
The const modifier is somewhat misleading here and
|
+ |
+ int i = 0; |
+ for (std::vector<AdblockPlus::SubscriptionPtr>::const_iterator it = subscriptions.begin(); |
+ it != subscriptions.end(); it++) |
+ { |
+ jobject subscription = pEnv->NewObject(cls, cid); |
+ pEnv->SetObjectField(subscription, ftitle, pEnv->NewStringUTF((*it)->GetProperty("title")->AsString().c_str())); |
+ pEnv->SetObjectField(subscription, furl, pEnv->NewStringUTF((*it)->GetProperty("url")->AsString().c_str())); |
+ pEnv->SetObjectArrayElement(ret, i, subscription); |
+ i++; |
+ } |
+ |
+ return ret; |
+} |
+ |
+void UpdateSubscriptionStatus(const std::string& url) |
+{ |
+ D(D_WARN, "UpdateSubscriptionStatus()"); |
+ |
+ AdblockPlus::SubscriptionPtr subscription = filterEngine->GetSubscription(url); |
+ std::string downloadStatus = subscription->GetProperty("downloadStatus")->IsNull() ? "" : subscription->GetProperty("downloadStatus")->AsString(); |
+ int64_t lastDownload = subscription->GetProperty("lastDownload")->AsInt(); |
+ |
+ std::string status = "synchronize_never"; |
+ int64_t time = 0; |
+ |
+ if (subscription->IsUpdating()) |
+ { |
+ status = "synchronize_in_progress"; |
+ } |
+ else if (!downloadStatus.empty() && downloadStatus != "synchronize_ok") |
+ { |
+ status = downloadStatus; |
+ } |
+ else if (lastDownload > 0) |
+ { |
+ time = lastDownload; |
+ status = "synchronize_last_at"; |
+ } |
+ |
+ JNIEnv* jniEnv = NULL; |
+ int stat = globalJvm->GetEnv((void **)&jniEnv, JNI_VERSION_1_6); |
+ if (stat == JNI_EDETACHED) |
+ { |
+ if (globalJvm->AttachCurrentThread(&jniEnv, NULL) != 0) |
+ throw std::runtime_error("Failed to get JNI environment"); |
+ } |
+ |
+ jstring jUrl = jniEnv->NewStringUTF(url.c_str()); |
+ jstring jStatus = jniEnv->NewStringUTF(status.c_str()); |
+ jlong jTime = time * 1000; |
+ |
+ static jclass cls = jniEnv->GetObjectClass(jniObject); |
+ static jmethodID mid = jniEnv->GetMethodID(cls, "onFilterChanged", "(Ljava/lang/String;Ljava/lang/String;J)V"); |
+ if (mid) |
+ jniEnv->CallVoidMethod(jniObject, mid, jUrl, jStatus, jTime); |
+ jniEnv->DeleteLocalRef(jUrl); |
+ jniEnv->DeleteLocalRef(jStatus); |
+ |
+ if (stat == JNI_EDETACHED) |
+ globalJvm->DetachCurrentThread(); |
+} |
+ |
+void FilterChangedCallback(const std::string& action, const std::string& url) |
Wladimir Palant
2013/09/12 11:31:14
I think that in the final revision of your libadbl
|
+{ |
+ D(D_WARN, "FilterChangedCallback()"); |
+ |
+ if (action == "subscription.lastDownload" || action == "subscription.downloadStatus") |
+ { |
+ UpdateSubscriptionStatus(url); |
Wladimir Palant
2013/09/12 11:31:14
Nit: Indentation is off here, need to convert a ta
|
+ } |
+} |
+ |
+void UpdateAvailableCallback(AdblockPlus::JsValueList& params) |
+{ |
+ //TODO Notify Java UI about available update |
+} |
+ |
+jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) |
+{ |
+ return JNI_VERSION_1_6; |
Wladimir Palant
2013/09/12 11:31:14
I don't think that we should hardcode the JNI vers
|
+} |
+ |
+void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved) |
+{ |
+} |
+ |
+JNIEXPORT void JNICALL Java_org_adblockplus_android_ABPEngine_initialize(JNIEnv *pEnv, jobject pObject, jstring basepath) |
+{ |
+ D(D_WARN, "nativeInitialize()"); |
+ int status = pEnv->GetJavaVM(&globalJvm); |
+ |
+ jniObject = pEnv->NewGlobalRef(pObject); |
+ |
+ const std::string path = GetString(pEnv, basepath); |
+ |
+ AdblockPlus::AppInfo appInfo; |
+ // FIXME Should be taken from Manifest |
Wladimir Palant
2013/09/12 11:31:14
Please use "TODO" instead of "FIXME", this is what
|
+ appInfo.version = "1.1.2"; |
+ appInfo.name = "adblockplusandroid"; |
+ appInfo.platform = "android"; |
Wladimir Palant
2013/09/12 11:31:14
Please note that this class changed in the current
|
+ |
+ AdblockPlus::JsEnginePtr jsEngine(AdblockPlus::JsEngine::New(appInfo)); |
+ |
+ AdblockPlus::DefaultFileSystem* defaultFileSystem = new AdblockPlus::DefaultFileSystem(); |
+ AndroidLogSystem* androidLogSystem = new AndroidLogSystem(); |
+ AndroidWebRequest* androidWebRequest = new AndroidWebRequest(globalJvm); |
Wladimir Palant
2013/09/12 11:31:14
I think your should assign to a shared pointer imm
|
+ |
+ defaultFileSystem->SetBasePath(path); |
Wladimir Palant
2013/09/12 11:31:14
You initialize the path variable 15 lines before i
|
+ jsEngine->SetLogSystem(AdblockPlus::LogSystemPtr(androidLogSystem)); |
+ jsEngine->SetFileSystem(AdblockPlus::FileSystemPtr(defaultFileSystem)); |
+ jsEngine->SetWebRequest(AdblockPlus::WebRequestPtr(androidWebRequest)); |
+ jsEngine->SetEventCallback("updateAvailable", std::tr1::bind(&UpdateAvailableCallback, std::tr1::placeholders::_1)); |
Wladimir Palant
2013/09/12 11:31:14
Why use std::tr1::bind() here instead of simply pa
|
+ |
+ filterEngine = new AdblockPlus::FilterEngine(jsEngine); |
+ filterEngine->SetFilterChangeCallback(&FilterChangedCallback); |
+} |
+ |
+JNIEXPORT void JNICALL Java_org_adblockplus_android_ABPEngine_release(JNIEnv *pEnv, jobject) |
+{ |
+ D(D_WARN, "nativeRelease()"); |
+ AdblockPlus::JsEnginePtr jsEngine = filterEngine->GetJsEngine(); |
+ jsEngine->RemoveEventCallback("updateAvailable"); |
+ filterEngine->RemoveFilterChangeCallback(); |
Wladimir Palant
2013/09/12 11:31:14
I think that you can rely on FilterEngine and JsEn
|
+ delete filterEngine; |
+ pEnv->DeleteGlobalRef(jniObject); |
+ jniObject = NULL; |
+ globalJvm = NULL; |
+} |
+ |
+JNIEXPORT jboolean JNICALL Java_org_adblockplus_android_ABPEngine_isFirstRun(JNIEnv *pEnv, jobject) |
+{ |
+ return filterEngine->IsFirstRun() ? JNI_TRUE : JNI_FALSE; |
+} |
+ |
+JNIEXPORT jobjectArray JNICALL Java_org_adblockplus_android_ABPEngine_getListedSubscriptions(JNIEnv *pEnv, jobject) |
+{ |
+ D(D_WARN, "getListedSubscriptions()"); |
+ const std::vector<AdblockPlus::SubscriptionPtr> subscriptions = filterEngine->GetListedSubscriptions(); |
Wladimir Palant
2013/09/12 11:31:14
Why are you catching exceptions in the GetRecommen
|
+ return subscriptionsAsJavaArray(pEnv, subscriptions); |
+} |
+ |
+JNIEXPORT jobjectArray JNICALL Java_org_adblockplus_android_ABPEngine_getRecommendedSubscriptions(JNIEnv *pEnv, jobject) |
+{ |
+ D(D_WARN, "getRecommendedSubscriptions()"); |
+ try |
+ { |
+ const std::vector<AdblockPlus::SubscriptionPtr> subscriptions = filterEngine->FetchAvailableSubscriptions(); |
+ return subscriptionsAsJavaArray(pEnv, subscriptions); |
+ } |
+ catch (const std::exception& e) |
+ { |
+ D(D_ERROR, "Exception: %s", e.what()); |
+ } |
+ catch (...) |
+ { |
+ D(D_ERROR, "Unknown exception"); |
+ } |
+ return NULL; |
Wladimir Palant
2013/09/12 11:31:14
I don't think that returning a null pointer makes
|
+} |
+ |
+JNIEXPORT void JNICALL Java_org_adblockplus_android_ABPEngine_addSubscription(JNIEnv *pEnv, jobject, jstring url) |
+{ |
+ D(D_WARN, "addSubscription()"); |
+ const std::string surl = GetString(pEnv, url); |
+ AdblockPlus::SubscriptionPtr subscription = filterEngine->GetSubscription(surl); |
+ subscription->AddToList(); |
+} |
+ |
+JNIEXPORT void JNICALL Java_org_adblockplus_android_ABPEngine_removeSubscription(JNIEnv *pEnv, jobject, jstring url) |
+{ |
+ D(D_WARN, "removeSubscription()"); |
+ const std::string surl = GetString(pEnv, url); |
+ AdblockPlus::SubscriptionPtr subscription = filterEngine->GetSubscription(surl); |
+ if (subscription->IsListed()) |
Wladimir Palant
2013/09/12 11:31:14
Calling IsListed() is unnecessary, that duplicates
|
+ { |
+ subscription->RemoveFromList(); |
+ } |
+} |
+ |
+JNIEXPORT void JNICALL Java_org_adblockplus_android_ABPEngine_refreshSubscription(JNIEnv *pEnv, jobject, jstring url) |
+{ |
+ D(D_WARN, "refreshSubscription()"); |
+ const std::string surl = GetString(pEnv, url); |
+ AdblockPlus::SubscriptionPtr subscription = filterEngine->GetSubscription(surl); |
+ subscription->UpdateFilters(); |
+} |
+ |
+JNIEXPORT void JNICALL Java_org_adblockplus_android_ABPEngine_actualizeSubscriptionStatus(JNIEnv *pEnv, jobject, jstring url) |
Wladimir Palant
2013/09/12 11:31:14
Nit: I don't think that "actualize" is really what
|
+{ |
+ D(D_WARN, "actualizeSubscriptionStatus()"); |
+ const std::string surl = GetString(pEnv, url); |
+ UpdateSubscriptionStatus(surl); |
+} |
+ |
+JNIEXPORT jboolean JNICALL Java_org_adblockplus_android_ABPEngine_matches(JNIEnv *pEnv, jobject, jstring url, jstring contentType, jstring documentUrl) |
+{ |
+ const std::string surl = GetString(pEnv, url); |
+ const std::string stype = GetString(pEnv, contentType); |
+ const std::string sdoc = GetString(pEnv, documentUrl); |
+ |
+ AdblockPlus::FilterPtr filter = filterEngine->Matches(surl, stype, sdoc); |
+ |
+ if (! filter) |
+ return JNI_FALSE; |
+ |
+ // hack: if there is no referrer block only if filter is domain-specific |
+ // (to re-enable in-app ads blocking, proposed on 12.11.2012 Monday meeting) |
+ // documentUrl contains the referrer (Android application special case) |
+ if (sdoc.empty() && (filter->GetProperty("text")->AsString()).find("||") != std::string::npos) |
Wladimir Palant
2013/09/12 11:31:14
Nit: the parentheses around filter->GetProperty("t
Felix Dahlke
2013/11/07 18:27:23
I don't really get what this is supposed to do - w
Wladimir Palant
2013/11/08 06:16:30
As the comment says, it looks for domain-specific
|
+ return JNI_FALSE; |
+ |
+ return filter->GetType() == AdblockPlus::Filter::TYPE_EXCEPTION ? JNI_FALSE : JNI_TRUE; |
+} |
+ |
+JNIEXPORT jobjectArray JNICALL Java_org_adblockplus_android_ABPEngine_getSelectorsForDomain(JNIEnv *pEnv, jobject, jstring domain) |
+{ |
+ const std::string sdomain = GetString(pEnv, domain); |
+ const std::vector<std::string> selectors = filterEngine->GetElementHidingSelectors(sdomain); |
+ |
+ static jclass cls = reinterpret_cast<jclass>(pEnv->NewGlobalRef(pEnv->FindClass("java/lang/String"))); |
+ |
+ D(D_WARN, "Selectors: %d", selectors.size()); |
+ const jobjectArray ret = (jobjectArray) pEnv->NewObjectArray(selectors.size(), cls, NULL); |
+ |
+ int i = 0; |
+ for (std::vector<std::string>::const_iterator it = selectors.begin(); |
+ it != selectors.end(); it++) |
+ { |
+ jstring selector = pEnv->NewStringUTF((*it).c_str()); |
+ pEnv->SetObjectArrayElement(ret, i, selector); |
+ pEnv->DeleteLocalRef(selector); |
+ i++; |
+ } |
+ |
+ return ret; |
+} |
+ |
+ |