mirror of https://github.com/roytam1/kmeleon.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1236 lines
36 KiB
1236 lines
36 KiB
/* |
|
* This program 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 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. If not, see <http://www.gnu.org/licenses/>. |
|
*/ |
|
|
|
|
|
#include "mozilla-config.h" |
|
#include <windows.h> |
|
#include <winsock.h> |
|
#include <stdio.h> |
|
#include <string> |
|
#include <iostream> |
|
#define XPCOM_GLUE |
|
#include "xpcom-config.h" |
|
#include <nsXPCOM.h> |
|
#include <nsCOMPtr.h> |
|
#include <nsISupports.h> |
|
#include <nsIComponentRegistrar.h> |
|
#include <nsIObserverService.h> |
|
#include <mozilla/ModuleUtils.h> |
|
#include <nsIServiceManager.h> |
|
#include <nsServiceManagerUtils.h> |
|
#include "nsICategoryManager.h" |
|
#include "nsIURI.h" |
|
#include "nsGenericFactory.h" |
|
#include "adcomp.h" |
|
#include "nsEmbedString.h" |
|
#include "nsPIDOMWindow.h" |
|
#include "nsIDOMWindow.h" |
|
#include "nsIDOMDocument.h" |
|
#include "nsIDOMLocation.h" |
|
#include "nsIEffectiveTLDService.h" |
|
#include "nsIDOMNode.h" |
|
#include "nsIPrefService.h" |
|
#include "nsIURI.h" |
|
#include "nsIFile.h" |
|
#include "nsIIOService.h" |
|
|
|
#include "nsIInterfaceRequestor.h" |
|
#include "nsILoadContext.h" |
|
#include "nsILoadGroup.h" |
|
#include "nsIHttpChannel.h" |
|
#include "nsIRunnable.h" |
|
#include "prthread.h" |
|
#include "nsIThreadManager.h" |
|
#include "nsIThread.h" |
|
|
|
|
|
|
|
#define KMELEON_PLUGIN_EXPORTS |
|
#include "kmeleon_plugin.h" |
|
//#include "KMeleonConst.h" |
|
|
|
#define PLUGIN_NAME "KMeleon Adblock" |
|
long DoMessage(const char *, const char *, const char *, long, long); |
|
kmeleonPlugin kPlugin = { |
|
KMEL_PLUGIN_VER, |
|
PLUGIN_NAME, |
|
DoMessage |
|
}; |
|
|
|
char logFile[MAX_PATH]; |
|
|
|
#include <string> |
|
#include <iostream> |
|
#include <sstream> |
|
#include <fstream> |
|
#include <unordered_map> |
|
#include <regex> |
|
#include <vector> |
|
#include <queue> |
|
|
|
bool InitSubs(); |
|
|
|
using namespace std; |
|
|
|
void LOG(const char* s) { |
|
|
|
nsCOMPtr<nsIPrefService> prefService = do_GetService(NS_PREFSERVICE_CONTRACTID); |
|
if (!prefService) return; |
|
nsCOMPtr<nsIPrefBranch> prefs; |
|
prefService->GetBranch("kmeleon.plugins.adblock.", getter_AddRefs(prefs)); |
|
if (!prefs) return; |
|
|
|
bool logging = false; |
|
prefs->GetBoolPref("logging", &logging); |
|
//kPlugin.kFuncs->GetPreference(PREF_BOOL, "kmeleon.plugins.adblock.logging", &logging, &logging); |
|
if (!logging) return; |
|
ofstream input(logFile, ofstream::app); |
|
input<<s<<"\n"; |
|
} |
|
|
|
static vector<std::string> &split(const string &s, const char delim, vector<std::string> &elems) { |
|
istringstream ss(s); |
|
string item; |
|
while (std::getline(ss, item, delim)) { |
|
elems.push_back(item); |
|
} |
|
return elems; |
|
} |
|
|
|
static vector<string> split(const string &s, const char delim) { |
|
vector<string> elems; |
|
split(s, delim, elems); |
|
return elems; |
|
} |
|
|
|
class Filter { |
|
protected: |
|
string text; |
|
Filter(const string& s) { text = s; }; |
|
|
|
|
|
|
|
public: |
|
static regex elemhideRegExp; |
|
static regex regexpRegExp; |
|
static regex optionsRegExp; |
|
|
|
string getText() const { return text; } |
|
static Filter* FromText(const string& s); |
|
virtual bool Matches(const string& location, unsigned type, const string& domain, bool thirdParty) = 0; |
|
virtual bool Blocking() const {return false;} |
|
|
|
}; |
|
|
|
regex Filter::elemhideRegExp("^([^\\/\\*\\|\\@\"!]*?)#(\\@)?(?:([\\w\\-]+|\\*)((?:\\([\\w\\-]+(?:[$^*]?=[^\\(\\)\"]*)?\\))*)|#([^{}]+))$"); |
|
regex Filter::regexpRegExp("^(@@)?\\/.*\\/(?:\\$~?[\\w\\-]+(?:=[^,\\s]+)?(?:,~?[\\w\\-]+(?:=[^,\\s]+)?)*)?$"); |
|
regex Filter::optionsRegExp("\\$(~?[\\w\\-]+(?:=[^,\\s]+)?(?:,~?[\\w\\-]+(?:=[^,\\s]+)?)*)$"); |
|
|
|
const char* typeMapKey[] = { |
|
"other", "script", "image", "stylesheet", |
|
"object", "subdocument", "document", "xbl", |
|
"ping", "xmlhttprequest", "object_subrequest", "dtd", |
|
"media", "font", "popup" }; |
|
|
|
const unsigned typeMapValue[] = {1,2,4,8,16,32,64,1,1,2048,4096,1,16384,32768,0x10000000}; |
|
const unsigned typePolicyValue[] = { |
|
nsIContentPolicy::TYPE_OTHER,nsIContentPolicy::TYPE_SCRIPT, |
|
nsIContentPolicy::TYPE_IMAGE,nsIContentPolicy::TYPE_STYLESHEET, |
|
nsIContentPolicy::TYPE_OBJECT,nsIContentPolicy::TYPE_SUBDOCUMENT, |
|
nsIContentPolicy::TYPE_DOCUMENT,nsIContentPolicy::TYPE_XBL, |
|
nsIContentPolicy::TYPE_PING,nsIContentPolicy::TYPE_XMLHTTPREQUEST, |
|
nsIContentPolicy::TYPE_OBJECT_SUBREQUEST,nsIContentPolicy::TYPE_DTD, |
|
nsIContentPolicy::TYPE_MEDIA,nsIContentPolicy::TYPE_FONT, 0xffff |
|
}; |
|
|
|
const size_t typeLength = sizeof(typePolicyValue)/sizeof(unsigned); |
|
|
|
class RegExpFilter:Filter { |
|
friend Filter; |
|
|
|
protected: |
|
int thirdParty; |
|
bool blocking; |
|
string regexpSrc; |
|
regex regexp; |
|
bool parsed; |
|
bool matchCase; |
|
bool collapse; |
|
string domainsTxt; |
|
unordered_map<string,bool> domains; |
|
vector<string> sitekeys; |
|
unsigned contentType; |
|
|
|
friend std::ostream& operator<<(std::ostream& os, const RegExpFilter& s) |
|
{ |
|
return os; |
|
} |
|
|
|
// Extraction operator |
|
friend std::istream& operator>>(std::istream& is, RegExpFilter& s) |
|
{ |
|
return is; |
|
} |
|
|
|
RegExpFilter(const string& s):Filter(s), |
|
thirdParty(-1), matchCase(false), collapse(false), parsed(false), blocking(true), contentType(0) |
|
{ |
|
string options; |
|
size_t optPos = string::npos; |
|
if (s[0] == '@' && s[1] == '@') blocking = false; |
|
if (s.find_first_of('$') != string::npos) { |
|
std::smatch match; |
|
if (regex_search(s, match, Filter::optionsRegExp)) { |
|
optPos = match.position(); |
|
options = match[1]; |
|
auto v = split(options, ','); |
|
string option, value; |
|
for (auto i=v.begin(); i!=v.end(); i++) { |
|
|
|
auto pos = i->find_first_of('='); |
|
if (pos != string::npos) { |
|
option = i->substr(0,pos); |
|
value = i->substr(pos+1); |
|
} else option = *i; |
|
replace(option.begin(), option.end(), '-', '_'); |
|
|
|
bool negate = false; |
|
if (option[0] == '~') { |
|
negate = true; |
|
option = option.substr(1); |
|
} |
|
|
|
if (option == "match_case") |
|
matchCase = !negate; |
|
else if (option == "domain") |
|
domainsTxt = value; |
|
else if (option == "third_party") |
|
thirdParty = !negate; |
|
else if (option == "collapse") |
|
collapse = 1; |
|
else if (option == "sitekey" && value.length()>0) |
|
sitekeys = split(value, '|'); |
|
else { |
|
bool found = false; |
|
for (int i=0;i<typeLength;i++) |
|
if (option.compare(typeMapKey[i])==0) { |
|
if (negate) { |
|
if (contentType == 0) contentType = 0x7FFFFFFF; |
|
contentType &= ~typeMapValue[i]; |
|
} else { |
|
contentType |= typeMapValue[i]; |
|
} |
|
found = true; |
|
break; |
|
} |
|
if (!found) |
|
LOG(("Unknow option " + option +": "+s).c_str()); |
|
} |
|
|
|
} |
|
} |
|
} |
|
|
|
if (contentType==0) contentType = 0x7FFFFFFF; |
|
regexpSrc = s.substr(blocking ? 0 : 2, blocking ? optPos : optPos - 2); |
|
if (regexpSrc.length()>2 && regexpSrc[0] == '/' && regexpSrc[regexpSrc.length()-1] == '/') { |
|
regexpSrc = regexpSrc.substr(1, regexpSrc.length()-2); |
|
} |
|
|
|
}; |
|
|
|
bool MatchDomain(string domain) { |
|
if (!domains.size() && domainsTxt.length()) { |
|
vector<string> _domains = split(domainsTxt, '|'); |
|
bool hasInclude = false; |
|
for (auto it=_domains.begin();it<_domains.end();it++) { |
|
bool inc = true; |
|
if ((*it)[0] == '~') { |
|
inc = false; |
|
} else hasInclude = true; |
|
|
|
domains.insert(pair<string,bool>((*it),inc)); |
|
} |
|
domains.insert(pair<string,bool>("",!hasInclude)); |
|
} |
|
|
|
if (!domains.size()) |
|
return true; |
|
|
|
while (true) { |
|
auto i = domains.find(domain); |
|
if (i != domains.end()) |
|
return i->second; |
|
|
|
size_t pos = domain.find_first_of('.'); |
|
if (pos == string::npos) break; |
|
domain = domain.substr(domain.find_first_of('.')+1); |
|
} |
|
|
|
return domains.find("")->second; |
|
} |
|
public: |
|
|
|
virtual bool Blocking() const { return blocking; } |
|
virtual bool Matches(const string& location, unsigned contentType, const string& docDomain, bool thirdParty) |
|
{ |
|
const char* searchList[] = {"\\*+", "\\^\\|$", "\\W", "\\\\\\*", "\\\\\\^", "^\\\\\\|\\\\\\|", "^\\\\\\|", "\\\\\\|$", "^(\\.\\*)", "(\\.\\*)$" }; |
|
const char* replaceList[] = {"*", "^", "\\$&", ".*", "(?:[\\x00-\\x24\\x26-\\x2C\\x2F\\x3A-\\x40\\x5B-\\x5E\\x60\\x7B-\\x7F]|$)", "^[\\w\\-]+:\\/+(?!\\/)(?:[^\\/]+\\.)?", "^", "$", "", "" }; |
|
const unsigned optionList[] = {std::tr1::regex_constants::match_any}; |
|
|
|
if (!MatchDomain(docDomain) || |
|
thirdParty && this->thirdParty == 0 || |
|
!thirdParty && this->thirdParty == 1 || |
|
((this->contentType & contentType) == 0)) |
|
return false; |
|
|
|
if (!parsed) { |
|
for (int i = 0; i<10; i++) { |
|
regex e (searchList[i]); |
|
regexpSrc = regex_replace(regexpSrc, e, string(replaceList[i])); |
|
} |
|
regexp.assign(regexpSrc, matchCase ? std::tr1::regex_constants::ECMAScript : std::tr1::regex_constants::icase); |
|
parsed = true; |
|
} |
|
|
|
return regex_search(location, regexp); |
|
} |
|
|
|
|
|
|
|
|
|
static RegExpFilter* FromText(const string& s) |
|
{ |
|
return new RegExpFilter(s); |
|
} |
|
|
|
}; |
|
|
|
Filter* Filter::FromText(const string& s) { |
|
if (!s.length() || s[0] == '!') return nullptr; |
|
if (s.find_first_of('#') != string::npos) { |
|
smatch match; |
|
if (regex_match(s, match, Filter::elemhideRegExp)) |
|
return nullptr; // TODO |
|
} |
|
return RegExpFilter::FromText(s); |
|
} |
|
|
|
class CacheComp { |
|
unordered_map<string,unsigned>* h; |
|
public: |
|
CacheComp(unordered_map<string,unsigned>* ah) : h(ah) {}; |
|
bool operator()(const string& x,const string& y) const { |
|
return h->at(x)<h->at(y); |
|
}; |
|
}; |
|
|
|
class AdRules { |
|
public: |
|
AdRules() : cacheSize(1000), cache(/*CacheComp(&cacheHit)*/) { |
|
}; |
|
void setCacheSize(size_t cs) { |
|
cacheSize = cs; |
|
} |
|
protected: |
|
size_t cacheSize; |
|
unordered_map<string,vector<Filter*>> wKeywordFilter; |
|
unordered_map<string,vector<Filter*>> bKeywordFilter; |
|
unordered_map<string,Filter*> cache; |
|
queue<string> cacheQueue; |
|
unordered_map<string,unsigned> cacheHit; |
|
//map<string,string> keywordByFilter; |
|
vector<Filter*> bFilterList; |
|
vector<Filter*> wFilterList; |
|
|
|
static regex keyRegex; |
|
string makeKey(Filter* f) |
|
{ |
|
string res; |
|
string text = f->getText(); |
|
if (regex_match(text, Filter::regexpRegExp)) |
|
return res; |
|
|
|
std::smatch match; |
|
if (regex_search(text, match, Filter::optionsRegExp)) { |
|
size_t optPos = match.position(); |
|
text = text.substr(0, optPos); |
|
} |
|
|
|
if (text.substr(0, 2) == "@@") |
|
text = text.substr(2); |
|
|
|
string::const_iterator first = text.begin(); |
|
string::const_iterator last = text.end(); |
|
|
|
unsigned resCount = 0xffff, resLength = 0; |
|
while (regex_search(first, last, match, keyRegex)) { |
|
string s = match[0].str().substr(1); |
|
|
|
unordered_map<string,vector<Filter*>>::const_iterator it; |
|
unsigned count; |
|
if (f->Blocking()) { |
|
it = bKeywordFilter.find(s); |
|
count = it != bKeywordFilter.end() ? it->second.capacity() : 0; |
|
} else { |
|
it = wKeywordFilter.find(s); |
|
count = it != wKeywordFilter.end() ? it->second.capacity() : 0; |
|
} |
|
|
|
if (count<resCount || (count == resCount && s.length() > resLength)) { |
|
res = s; |
|
resLength = res.length(); |
|
resCount = count; |
|
} |
|
|
|
first += match.position() + match.length(); |
|
} |
|
return res; |
|
} |
|
public: |
|
size_t count() |
|
{ |
|
return bKeywordFilter.size() + wKeywordFilter.size(); |
|
} |
|
|
|
bool disabled() |
|
{ |
|
bool res = false; |
|
nsCOMPtr<nsIPrefService> prefService = do_GetService(NS_PREFSERVICE_CONTRACTID); |
|
if (!prefService) return false; |
|
nsCOMPtr<nsIPrefBranch> prefs; |
|
prefService->GetBranch("kmeleon.plugins.adblock.", getter_AddRefs(prefs)); |
|
if (!prefs) return false; |
|
prefs->GetBoolPref("disabled", &res); |
|
//kPlugin.kFuncs->GetPreference(PREF_BOOL, "kmeleon.plugins.adblock.disabled", &res, &res); |
|
return res; |
|
} |
|
|
|
void add(Filter* f) |
|
{ |
|
string key = makeKey(f); |
|
|
|
if (f->Blocking()) { |
|
auto it = bKeywordFilter.find(key); |
|
if (it == bKeywordFilter.end()) { |
|
vector<Filter*> v; |
|
v.push_back(f); |
|
bKeywordFilter.insert( pair<string, vector<Filter*>>(key, v)); |
|
} else it->second.push_back(f); |
|
bFilterList.push_back(f); |
|
} else { |
|
auto it = wKeywordFilter.find(key); |
|
if (it == wKeywordFilter.end()) { |
|
vector<Filter*> v; |
|
v.push_back(f); |
|
wKeywordFilter.insert( pair<string, vector<Filter*>>(key, v)); |
|
} else it->second.push_back(f); |
|
wFilterList.push_back(f); |
|
} |
|
} |
|
|
|
void reset() |
|
{ |
|
for (auto i=bFilterList.begin();i<bFilterList.end();i++) { |
|
delete (*i); |
|
} |
|
for (auto i=wFilterList.begin();i<wFilterList.end();i++) { |
|
delete (*i); |
|
} |
|
bKeywordFilter.empty(); |
|
bFilterList.empty(); |
|
wKeywordFilter.empty(); |
|
wFilterList.empty(); |
|
} |
|
|
|
Filter* match(const string& location, unsigned type, const string& domain, bool thirdParty) |
|
{ |
|
string key = location + " " + domain + " " + to_string((_ULonglong)type) + " " + (thirdParty ? "1" : "0"); |
|
auto hit = cacheHit.find(key); |
|
if (hit != cacheHit.end()) hit->second++; else cacheHit[key] = 1; |
|
auto it = cache.find(key); |
|
if (it != cache.end()) return it->second; |
|
|
|
Filter* m = _match(location, type, domain, thirdParty); |
|
|
|
if (cache.size() > cacheSize) { |
|
cache.erase(cacheQueue.front()); |
|
cacheQueue.pop(); |
|
} |
|
cache[key] = m; |
|
cacheQueue.push(key); |
|
return m; |
|
} |
|
|
|
Filter* _match(const string& location, unsigned type, const string& domain, bool thirdParty) |
|
{ |
|
|
|
|
|
vector<string> keywords; |
|
smatch match; |
|
regex e("[a-z0-9%]{3,}"); |
|
string::const_iterator first = location.begin(); |
|
string::const_iterator last = location.end(); |
|
while (regex_search(first, last, match, e)) { |
|
keywords.push_back(match[0].str()); |
|
first += match.position() + match.length(); |
|
} |
|
keywords.push_back(""); |
|
|
|
for (auto i=keywords.begin();i<keywords.end();i++) { |
|
auto it = wKeywordFilter.find(*i); |
|
if (it != wKeywordFilter.end()) { |
|
for (auto itt=it->second.begin();itt<it->second.end();itt++) |
|
if ((*itt)->Matches(location, type, domain, thirdParty)) |
|
return *itt; |
|
} |
|
} |
|
for (auto i=keywords.begin();i<keywords.end();i++) { |
|
auto itb = bKeywordFilter.find(*i); |
|
if (itb != bKeywordFilter.end()) { |
|
for (auto itt=itb->second.begin();itt<itb->second.end();itt++) |
|
if ((*itt)->Matches(location, type, domain, thirdParty)) |
|
return *itt; |
|
} |
|
} |
|
|
|
return nullptr; |
|
} |
|
|
|
}; |
|
|
|
static AdRules rules; |
|
regex AdRules::keyRegex("[^a-z0-9%*][a-z0-9%]{3,}(?=[^a-z0-9%*])"); |
|
|
|
|
|
class DeferClose: public nsIRunnable |
|
{ |
|
nsCOMPtr<nsIDOMWindow> mDom; |
|
public: |
|
NS_DECL_ISUPPORTS |
|
|
|
DeferClose(nsIDOMWindow* dom) { |
|
mDom = dom; |
|
}; |
|
|
|
~DeferClose() { |
|
} |
|
|
|
NS_IMETHODIMP Run() { |
|
mDom->Close(); |
|
return NS_OK; |
|
}; |
|
}; |
|
|
|
NS_IMPL_ISUPPORTS(DeferClose, nsIRunnable); |
|
|
|
Policy::Policy() |
|
{ |
|
nsCOMPtr<nsIObserverService> observerService = do_GetService("@mozilla.org/observer-service;1"); |
|
if (!observerService) return; |
|
observerService->AddObserver(this, "http-on-opening-request", false); |
|
observerService->AddObserver(this, "content-document-global-created", false); |
|
if (!rules.count()) InitSubs(); |
|
} |
|
|
|
bool Policy::IsInWhiteList(nsIURI* aUri) |
|
{ |
|
nsCString scheme; |
|
aUri->GetScheme(scheme); |
|
if (scheme.Compare("chrome") == 0 || scheme.Compare("about") == 0) |
|
return true; |
|
return false; |
|
} |
|
|
|
bool Policy::Process(nsIDOMWindow* wnd, nsIDOMNode* node, nsIURI* aContentLocation, unsigned int contentType) |
|
{ |
|
nsCString domain; |
|
nsCOMPtr<nsIDOMLocation> location; |
|
wnd->GetLocation(getter_AddRefs(location)); |
|
if (location) { |
|
nsString _domain; |
|
location->GetHost(_domain); |
|
NS_UTF16ToCString(_domain, NS_CSTRING_ENCODING_UTF8, domain); |
|
} |
|
|
|
bool thirdParty = false; |
|
if (!tld) tld = do_GetService("@mozilla.org/network/effective-tld-service;1"); |
|
if (tld) { |
|
nsCString ret; |
|
nsresult rv = tld->GetBaseDomain(aContentLocation, 0, ret); |
|
if (NS_SUCCEEDED(rv)) { |
|
nsCString ret2; |
|
rv = tld->GetBaseDomainFromHost(domain, 0, ret2); |
|
if (NS_SUCCEEDED(rv)) { |
|
thirdParty = ret.Compare(ret2) != 0; |
|
} |
|
} |
|
if (NS_FAILED(rv)) { |
|
aContentLocation->GetHost(ret); |
|
thirdParty = ret.Compare(domain) != 0; |
|
} |
|
} |
|
|
|
nsCString spec; |
|
aContentLocation->GetSpec(spec); |
|
|
|
string loc(spec.get()); |
|
Filter* res = rules.match(loc, contentType, string(domain.get()), thirdParty); |
|
if (res) LOG(((res->Blocking()?"Block: ":"Accept: ")+loc+" / Rule: "+res->getText()).c_str()); |
|
return (res && res->Blocking()) ? true : false; |
|
} |
|
|
|
NS_IMETHODIMP Policy::ShouldLoad(nsContentPolicyType aContentType, nsIURI *aContentLocation, nsIURI *aRequestOrigin, nsISupports *aContext, const nsACString & aMimeTypeGuess, nsISupports *aExtra, nsIPrincipal *aRequestPrincipal, int16_t *_retval) |
|
{ |
|
*_retval = nsIContentPolicy::ACCEPT; |
|
if (!aContext || aContentType == Policy::TYPE_DOCUMENT) |
|
return NS_OK; |
|
|
|
if (IsInWhiteList(aContentLocation)) |
|
return NS_OK; |
|
|
|
if (rules.disabled()) |
|
return NS_OK; |
|
|
|
unsigned contentType = 0; |
|
for (int i=0;i<typeLength;i++) |
|
if (aContentType == typePolicyValue[i]) { |
|
contentType = typeMapValue[i]; |
|
break; |
|
} |
|
|
|
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aContext); |
|
nsCOMPtr<nsIDOMDocument> owner; |
|
node->GetOwnerDocument(getter_AddRefs(owner)); |
|
if (!owner) { |
|
nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(aContext); |
|
if (!doc) return NS_OK; |
|
doc->GetOwnerDocument(getter_AddRefs(owner)); |
|
if (!owner) owner = doc; |
|
} |
|
|
|
nsCOMPtr<nsIDOMWindow> wnd; |
|
owner->GetDefaultView(getter_AddRefs(wnd)); |
|
if (!wnd) return NS_OK; |
|
|
|
bool res = Process(wnd, node, aContentLocation, contentType); |
|
*_retval = res ? nsIContentPolicy::REJECT_REQUEST : nsIContentPolicy::ACCEPT; |
|
return NS_OK; |
|
|
|
nsCString domain; |
|
nsCOMPtr<nsIDOMLocation> location; |
|
wnd->GetLocation(getter_AddRefs(location)); |
|
if (location) { |
|
nsString _domain; |
|
location->GetHost(_domain); |
|
NS_UTF16ToCString(_domain, NS_CSTRING_ENCODING_UTF8, domain); |
|
} |
|
|
|
bool thirdParty = false; |
|
if (!tld) tld = do_GetService("@mozilla.org/network/effective-tld-service;1"); |
|
if (tld) { |
|
nsCString ret; |
|
nsresult rv = tld->GetBaseDomain(aContentLocation, 0, ret); |
|
if (NS_SUCCEEDED(rv)) { |
|
nsCString ret2; |
|
rv = tld->GetBaseDomainFromHost(domain, 0, ret2); |
|
if (NS_SUCCEEDED(rv)) { |
|
thirdParty = ret.Compare(ret2) != 0; |
|
} |
|
} |
|
if (NS_FAILED(rv)) { |
|
aContentLocation->GetHost(ret); |
|
thirdParty = ret.Compare(domain) != 0; |
|
} |
|
} |
|
|
|
nsCString spec; |
|
aContentLocation->GetSpec(spec); |
|
|
|
string loc(spec.get()); |
|
Filter* filter = rules.match(loc, contentType, string(domain.get()), thirdParty); |
|
if (res) LOG(((filter->Blocking()?"Block: ":"Accept: ")+loc+" / Rule: "+filter->getText()).c_str()); |
|
|
|
*_retval = (filter && filter->Blocking()) ? nsIContentPolicy::REJECT_REQUEST : nsIContentPolicy::ACCEPT; |
|
return NS_OK; |
|
} |
|
|
|
NS_IMETHODIMP Policy::ShouldProcess(nsContentPolicyType aContentType, nsIURI *aContentLocation, nsIURI *aRequestOrigin, nsISupports *aContext, const nsACString & aMimeType, nsISupports *aExtra, nsIPrincipal *aRequestPrincipal, int16_t *_retval) |
|
{ |
|
*_retval = nsIContentPolicy::ACCEPT; |
|
return NS_OK; |
|
} |
|
|
|
|
|
|
|
NS_IMETHODIMP Policy::Observe(nsISupports *aSubject, const char * aTopic, const PRUnichar * aData) |
|
{ |
|
static bool popup = false; |
|
static vector<nsIDOMWindow*> domPopup; |
|
if (strcmp(aTopic, "content-document-global-created") == 0) |
|
{ |
|
nsCOMPtr<nsPIDOMWindow> dom = do_QueryInterface(aSubject); |
|
if (!dom) return NS_OK; |
|
|
|
nsCOMPtr<nsPIDOMWindow> opener = dom->GetOpener(); |
|
if (!opener) return NS_OK; |
|
|
|
nsCOMPtr<nsIDOMLocation> location; |
|
dom->GetLocation(getter_AddRefs(location)); |
|
if (!location) return NS_OK; |
|
|
|
nsString href; |
|
location->GetHref(href); |
|
/*if (href.Length() && href.Compare(L"about:blank") != 0) { |
|
nsCOMPtr<nsIDOMDocument> document; |
|
opener->GetDocument(getter_AddRefs(document)); |
|
nsCOMPtr<nsIIOService> ios = do_GetService("@mozilla.org/network/io-service;1"); |
|
NS_ENSURE_TRUE(ios, NS_OK); |
|
nsCOMPtr<nsIURI> uri; |
|
nsCString _href; |
|
NS_UTF16ToCString(href, NS_CSTRING_ENCODING_UTF8, _href); |
|
ios->NewURI(_href, nullptr, nullptr, getter_AddRefs(uri)); |
|
if (Process(opener, document, uri, 0x10000000)) |
|
dom->Close(); |
|
} |
|
else */domPopup.push_back(dom); |
|
|
|
} |
|
|
|
if (strcmp(aTopic, "http-on-opening-request") == 0) |
|
{ |
|
if (domPopup.size()) { |
|
nsCOMPtr<nsIHttpChannel> channel = do_QueryInterface(aSubject); |
|
if (!channel) return NS_OK; |
|
|
|
nsCOMPtr<nsIDOMWindow> dom; |
|
nsCOMPtr<nsIInterfaceRequestor> callbacks; |
|
channel->GetNotificationCallbacks(getter_AddRefs(callbacks)); |
|
if (callbacks) { |
|
nsCOMPtr<nsILoadContext> context; |
|
callbacks->GetInterface(NS_GET_IID(nsILoadContext), getter_AddRefs(context)); |
|
if (context) { |
|
context->GetAssociatedWindow(getter_AddRefs(dom)); |
|
} |
|
} |
|
if (!dom) { |
|
nsCOMPtr<nsILoadGroup> group; |
|
channel->GetLoadGroup(getter_AddRefs(group)); |
|
if (group) { |
|
group->GetNotificationCallbacks(getter_AddRefs(callbacks)); |
|
if (callbacks) { |
|
nsCOMPtr<nsILoadContext> context; |
|
callbacks->GetInterface(NS_GET_IID(nsILoadContext), getter_AddRefs(context)); |
|
if (context) { |
|
context->GetAssociatedWindow(getter_AddRefs(dom)); |
|
} |
|
} |
|
} |
|
} |
|
|
|
if (!dom) return NS_OK; |
|
|
|
auto it = find(domPopup.begin(), domPopup.end(), dom); |
|
if (it == domPopup.end()) |
|
return NS_OK; |
|
|
|
domPopup.erase(it); |
|
nsCOMPtr<nsIURI> uri; |
|
channel->GetURI(getter_AddRefs(uri)); |
|
|
|
nsCOMPtr<nsPIDOMWindow> pdom = do_QueryInterface(dom); |
|
nsCOMPtr<nsPIDOMWindow> opener = pdom->GetOpener(); |
|
if (!opener) return NS_OK; |
|
|
|
nsCOMPtr<nsIDOMDocument> document; |
|
opener->GetDocument(getter_AddRefs(document)); |
|
|
|
if (Process(opener, document, uri, 0x10000000)) { |
|
nsCOMPtr<nsIThreadManager> tm = do_GetService("@mozilla.org/thread-manager;1"); |
|
if (!tm) return NS_OK; |
|
nsCOMPtr<nsIThread> thread; |
|
tm->GetCurrentThread(getter_AddRefs(thread)); |
|
if (!thread) return NS_OK; |
|
thread->Dispatch(new DeferClose(dom), nsIThread::DISPATCH_NORMAL); |
|
} |
|
} |
|
} |
|
|
|
return NS_OK; |
|
} |
|
|
|
NS_IMPL_ISUPPORTS(Policy, nsIContentPolicy, nsIObserver); |
|
|
|
NS_GENERIC_FACTORY_CONSTRUCTOR(Policy) |
|
|
|
static const mozilla::Module::CIDEntry kBrowserCIDs[] = { |
|
{ &kPolicyCID,true, NULL, PolicyConstructor }, |
|
{ NULL } |
|
}; |
|
|
|
static const mozilla::Module::ContractIDEntry kBrowserContracts[] = { |
|
{"@kmeleon/adblock;1", &kPolicyCID}, |
|
{ NULL } |
|
}; |
|
|
|
static const mozilla::Module::CategoryEntry kCategory[] = { |
|
{"content-policy", "adblock", "@kmeleon/adblock;1"}, |
|
{ NULL } |
|
}; |
|
|
|
|
|
static const mozilla::Module kBrowserModule = { |
|
mozilla::Module::kVersion, |
|
kBrowserCIDs, |
|
kBrowserContracts, |
|
kCategory |
|
}; |
|
|
|
NSMODULE_DEFN(nsBrowserCompsModule) = &kBrowserModule; |
|
|
|
static const nsModuleComponentInfo components = |
|
{ |
|
"Adblock content policy", |
|
POLICY_CID, |
|
"@kmeleon/adblock;1", |
|
PolicyConstructor |
|
}; |
|
|
|
static nsCOMPtr<nsIGenericFactory> componentFactory; |
|
extern nsresult NS_NewGenericFactory(nsIGenericFactory* *result, |
|
const nsModuleComponentInfo *info); |
|
|
|
using namespace std; |
|
|
|
#if 0 |
|
|
|
#define BUFFERSIZE 4096 |
|
bool DownloadFile(string url, LPCSTR filename){ |
|
string request; // HTTP Header // |
|
|
|
char buffer[BUFFERSIZE]; |
|
struct sockaddr_in serveraddr; |
|
int sock; |
|
|
|
WSADATA wsaData; |
|
int port = 80; |
|
|
|
// Remove's http:// part // |
|
if(url.find("http://") != -1){ |
|
string temp = url; |
|
url = temp.substr(url.find("http://") + 7); |
|
} |
|
|
|
// Split host and file location // |
|
int dm = url.find("/"); |
|
string file = url.substr(dm); |
|
string shost = url.substr(0, dm); |
|
|
|
// Generate http header // |
|
request += "GET " + file + " HTTP/1.0\r\n"; |
|
request += "Host: " + shost + "\r\n"; |
|
request += "\r\n"; |
|
|
|
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) |
|
return FALSE; |
|
|
|
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) |
|
return FALSE; |
|
|
|
memset(&serveraddr, 0, sizeof(serveraddr)); |
|
|
|
// ip address of link // |
|
hostent *record = gethostbyname(shost.c_str()); |
|
in_addr *address = (in_addr * )record->h_addr; |
|
string ipd = inet_ntoa(* address); |
|
const char *ipaddr = ipd.c_str(); |
|
|
|
serveraddr.sin_family = AF_INET; |
|
serveraddr.sin_addr.s_addr = inet_addr(ipaddr); |
|
serveraddr.sin_port = htons(port); |
|
|
|
if (connect(sock, (struct sockaddr *) &serveraddr, sizeof(serveraddr)) < 0) |
|
return FALSE; |
|
|
|
if (send(sock, request.c_str(), request.length(), 0) != request.length()) |
|
return FALSE; |
|
|
|
int nRecv, npos; |
|
nRecv = recv(sock, (char*)&buffer, BUFFERSIZE, 0); |
|
|
|
// getting end of header // |
|
string str_buff = buffer; |
|
npos = str_buff.find("\r\n\r\n"); |
|
|
|
// open the file in the beginning // |
|
HANDLE hFile; |
|
hFile = CreateFileA(filename, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); |
|
SetFilePointer(hFile, 0, NULL, FILE_BEGIN); |
|
|
|
// Download file // |
|
DWORD ss; |
|
while((nRecv > 0) && (nRecv != INVALID_SOCKET)){ |
|
if(npos > 0){ |
|
char bf[BUFFERSIZE]; |
|
// copy from end position of header // |
|
memcpy(bf, buffer + (npos + 4), nRecv - (npos + 4)); |
|
WriteFile(hFile, bf,nRecv - (npos + 4), &ss, NULL); |
|
}else{ |
|
// write normally if end not found // |
|
WriteFile(hFile, buffer, nRecv, &ss, NULL); |
|
} |
|
|
|
// buffer cleanup // |
|
ZeroMemory(&buffer, sizeof(buffer)); |
|
nRecv = recv(sock, (char*)&buffer, BUFFERSIZE, 0); |
|
str_buff = buffer; |
|
npos = str_buff.find("\r\n\r\n"); |
|
} |
|
|
|
// Close connection and handle // |
|
CloseHandle(hFile); |
|
closesocket(sock); |
|
WSACleanup(); |
|
|
|
return TRUE; |
|
} |
|
|
|
#endif |
|
|
|
#include "nsIWebBrowserPersist.h" |
|
#include "nsCWebBrowserPersist.h" |
|
#include "nsComponentManagerUtils.h" |
|
#include "nsIIOService.h" |
|
#include "nsIWebProgressListener.h" |
|
#include "nsIHttpChannel.h" |
|
|
|
/* void onStateChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long aStateFlags, in nsresult aStatus); */ |
|
NS_IMETHODIMP Subscriptions::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, uint32_t aStateFlags, nsresult aStatus) |
|
{ |
|
if ( (aStateFlags & nsIWebProgressListener::STATE_STOP)) { |
|
if (NS_SUCCEEDED(aStatus)) { |
|
LOG(("Download success " + (*(dwnIt-1))).c_str()); |
|
std::ifstream src(tmpFile); |
|
std::ofstream dst(adFile, ofstream::app); |
|
dst << src.rdbuf() << "\n"; |
|
dst.close(); |
|
src.close(); |
|
_wremove(tmpFile.c_str()); |
|
_Download(); |
|
|
|
} else { |
|
LOG(("Download failed " + (*(dwnIt - 1))).c_str()); |
|
} |
|
return NS_OK; |
|
} |
|
|
|
if (aStateFlags & nsIWebProgressListener::STATE_START) { |
|
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest); |
|
if (!channel) return NS_OK; |
|
nsCOMPtr<nsIHttpChannel> httpchannel(do_QueryInterface(channel)); |
|
if (httpchannel) { |
|
httpchannel->GetResponseHeader(nsEmbedCString("content-disposition"), mContentDisposition); |
|
} |
|
} |
|
|
|
return NS_OK; |
|
} |
|
|
|
/* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */ |
|
NS_IMETHODIMP Subscriptions::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, int32_t aCurSelfProgress, int32_t aMaxSelfProgress, int32_t aCurTotalProgress, int32_t aMaxTotalProgress) |
|
{ |
|
return NS_OK; |
|
} |
|
|
|
/* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI aLocation, [optional] in unsigned long aFlags); */ |
|
NS_IMETHODIMP Subscriptions::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *aLocation, uint32_t aFlags) |
|
{ |
|
return NS_OK; |
|
} |
|
|
|
/* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */ |
|
NS_IMETHODIMP Subscriptions::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const PRUnichar * aMessage) |
|
{ |
|
return NS_OK; |
|
} |
|
|
|
/* void onSecurityChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long aState); */ |
|
NS_IMETHODIMP Subscriptions::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, uint32_t aState) |
|
{ |
|
return NS_OK; |
|
} |
|
|
|
#include "nsDirectoryServiceUtils.h" |
|
#include "nsAppDirectoryServiceDefs.h" |
|
Subscriptions::Subscriptions() |
|
{ |
|
nsCOMPtr<nsIFile> nsDir; |
|
nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(nsDir)); |
|
if (NS_FAILED(rv)) return; |
|
|
|
nsEmbedString pathBuf; |
|
rv = nsDir->GetPath(pathBuf); |
|
|
|
tmpFile = wstring(pathBuf.get()) + L"\\adblocktmp.txt"; |
|
adFile = wstring(pathBuf.get()) + L"\\adblock.txt"; |
|
cacheFile = wstring(pathBuf.get()) + L"\\adblock.cache"; |
|
} |
|
|
|
bool Subscriptions::Parse() |
|
{ |
|
std::ifstream infile(cacheFile); |
|
if (infile.good()) { |
|
WIN32_FILE_ATTRIBUTE_DATA attr, attr2; |
|
GetFileAttributesExW(cacheFile.c_str(), GetFileExInfoStandard, &attr); |
|
GetFileAttributesExW(adFile.c_str(), GetFileExInfoStandard, &attr2); |
|
if (CompareFileTime(&attr2.ftLastWriteTime, &attr2.ftLastWriteTime) < 0) { |
|
|
|
} |
|
} |
|
|
|
std::ofstream cache(cacheFile); |
|
std::ifstream input(adFile); |
|
std::string line; |
|
while( std::getline( input, line ) ) { |
|
Filter* f = Filter::FromText(line); |
|
if (!f) continue; |
|
rules.add(f); |
|
} |
|
cache.close(); |
|
return true; |
|
} |
|
|
|
bool Subscriptions::_Download() |
|
{ |
|
if (dwnIt == subscriptionList.end()) { |
|
Parse(); |
|
return true; |
|
} |
|
|
|
persist = do_CreateInstance(NS_WEBBROWSERPERSIST_CONTRACTID); |
|
if (!persist) return false; |
|
|
|
persist->SetPersistFlags( |
|
nsIWebBrowserPersist::PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION| |
|
nsIWebBrowserPersist::PERSIST_FLAGS_REPLACE_EXISTING_FILES); |
|
|
|
persist->SetProgressListener(this); |
|
|
|
nsCOMPtr<nsIIOService> ios = do_GetService("@mozilla.org/network/io-service;1"); |
|
NS_ENSURE_TRUE(ios, false); |
|
|
|
nsCOMPtr<nsIURI> uri; |
|
ios->NewURI(nsEmbedCString((*dwnIt).c_str()), nullptr, nullptr, getter_AddRefs(uri)); |
|
nsCOMPtr<nsIFile> file; |
|
NS_NewLocalFile(nsDependentString(tmpFile.c_str()), TRUE, getter_AddRefs(file)); |
|
|
|
LOG(("Downloading: " + (*dwnIt)).c_str()); |
|
dwnIt++; |
|
nsresult rv = persist->SaveURI(uri, nullptr, nullptr, 0, nullptr, nullptr, file, nullptr); |
|
NS_ENSURE_SUCCESS(rv, false); |
|
return true; |
|
} |
|
|
|
bool Subscriptions::Add(const char* s) |
|
{ |
|
subscriptionList.push_back(s); |
|
return true; |
|
} |
|
|
|
bool Subscriptions::Download() |
|
{ |
|
_wremove(adFile.c_str()); |
|
dwnIt = subscriptionList.begin(); |
|
if (dwnIt == subscriptionList.end()) return true; |
|
_Download(); |
|
return true; |
|
} |
|
|
|
bool Subscriptions::RulesExists() |
|
{ |
|
std::ifstream infile(adFile); |
|
return infile.good(); |
|
} |
|
|
|
NS_IMPL_ISUPPORTS(Subscriptions, nsIWebProgressListener) |
|
|
|
bool InitSubs() |
|
{ |
|
rules.reset(); |
|
Subscriptions* s = new Subscriptions(); |
|
if (!s->RulesExists()) |
|
{ |
|
nsCOMPtr<nsIPrefService> prefService = do_GetService(NS_PREFSERVICE_CONTRACTID); |
|
if (!prefService) return false; |
|
nsCOMPtr<nsIPrefBranch> prefs; |
|
prefService->GetBranch("kmeleon.plugins.adblock.", getter_AddRefs(prefs)); |
|
if (!prefs) return false; |
|
|
|
nsCString nsSubs; |
|
prefs->GetCharPref("subscriptions", getter_Copies(nsSubs)); |
|
if (!nsSubs.Length()) return true; |
|
vector<string> subs = split(nsSubs.get(),'|'); |
|
|
|
/*int len = kPlugin.kFuncs->GetPreference(PREF_STRING, "kmeleon.plugins.adblock.subscriptions", nullptr, nullptr); |
|
if (!len) return true; |
|
|
|
char* _subs = new char[len+1]; |
|
kPlugin.kFuncs->GetPreference(PREF_STRING, "kmeleon.plugins.adblock.subscriptions", _subs, _subs); |
|
vector<string> subs = split(_subs,'|'); |
|
delete _subs; */ |
|
|
|
for (auto it = subs.begin();it<subs.end();it++) |
|
s->Add((*it).c_str()); |
|
|
|
return s->Download(); |
|
} |
|
else |
|
s->Parse(); |
|
delete s; |
|
return true; |
|
} |
|
|
|
BOOL Init() |
|
{ |
|
nsCOMPtr<nsIComponentRegistrar> compReg; |
|
nsresult rv = NS_GetComponentRegistrar(getter_AddRefs(compReg)); |
|
NS_ENSURE_SUCCESS(rv, FALSE); |
|
|
|
rv = NS_NewGenericFactory(getter_AddRefs(componentFactory), &components); |
|
if (NS_FAILED(rv) || !componentFactory) |
|
return FALSE; |
|
|
|
rv = compReg->RegisterFactory(components.mCID, |
|
components.mDescription, |
|
components.mContractID, |
|
componentFactory); |
|
|
|
nsCOMPtr<nsIServiceManager> servMan; |
|
rv = NS_GetServiceManager(getter_AddRefs(servMan)); |
|
NS_ENSURE_SUCCESS(rv, FALSE); |
|
|
|
nsCOMPtr<nsICategoryManager> catman; |
|
rv = servMan->GetServiceByContractID("@mozilla.org/categorymanager;1", NS_GET_IID(nsICategoryManager), getter_AddRefs(catman)); |
|
NS_ENSURE_SUCCESS(rv, FALSE); |
|
|
|
rv = catman->AddCategoryEntry("content-policy", components.mContractID, components.mContractID, false, true, nullptr); |
|
NS_ENSURE_SUCCESS(rv, FALSE); |
|
//rv = catman->AddCategoryEntry("net-channel-event-sinks", components.mContractID, components.mContractID, false, true, nullptr); |
|
//NS_ENSURE_SUCCESS(rv, FALSE); |
|
|
|
InitSubs(); |
|
|
|
char rulesFile[MAX_PATH], profDir[MAX_PATH]; |
|
kPlugin.kFuncs->GetFolder(FolderType::ProfileFolder, profDir, MAX_PATH); |
|
|
|
strcpy(rulesFile, profDir); |
|
strcat(rulesFile, "\\adblock.txt"); |
|
strcpy(logFile, profDir); |
|
strcat(logFile, "\\adblock.log"); |
|
|
|
size_t cacheSize = 1000; |
|
cacheSize = kPlugin.kFuncs->GetPreference(PREF_INT, "kmeleon.plugins.adblock.cacheSize", &cacheSize, &cacheSize); |
|
rules.setCacheSize(cacheSize); |
|
return TRUE; |
|
} |
|
|
|
BOOL Quit() |
|
{ |
|
rules.reset(); |
|
nsresult rv; |
|
nsCOMPtr<nsIComponentRegistrar> compReg; |
|
rv = NS_GetComponentRegistrar(getter_AddRefs (compReg)); |
|
NS_ENSURE_SUCCESS(rv, FALSE); |
|
|
|
nsCOMPtr<nsICategoryManager> catman = do_GetService("@mozilla.org/categorymanager;1"); |
|
if (catman) catman->DeleteCategoryEntry("content-policy", components.mContractID, false); |
|
|
|
/*nsCOMPtr<nsIServiceManager> servMan; |
|
rv = NS_GetServiceManager(getter_AddRefs(servMan)); |
|
NS_ENSURE_SUCCESS(rv, FALSE); |
|
|
|
nsCOMPtr<nsICategoryManager> catman; |
|
rv = servMan->GetServiceByContractID("@mozilla.org/categorymanager;1", NS_GET_IID(nsICategoryManager), getter_AddRefs(catman)); |
|
NS_ENSURE_SUCCESS(rv, FALSE); |
|
|
|
rv = catman->DeleteCategoryEntry("content-policy", components.mContractID, false); |
|
NS_ENSURE_SUCCESS(rv, FALSE);*/ |
|
|
|
rv = compReg->UnregisterFactory(components.mCID, componentFactory); |
|
return NS_SUCCEEDED(rv) ? TRUE : FALSE; |
|
} |
|
|
|
#include "nsIWebBrowser.h" |
|
|
|
void Create(HWND hwnd) |
|
{ |
|
nsCOMPtr<nsIWebBrowser> browser; |
|
kPlugin.kFuncs->GetMozillaWebBrowser(hwnd, getter_AddRefs(browser)); |
|
if (!browser) return; |
|
|
|
nsCOMPtr<nsIDOMWindow> dom; |
|
browser->GetContentDOMWindow(getter_AddRefs(dom)); |
|
if (!dom) return; |
|
|
|
nsCOMPtr<nsPIDOMWindow> pdom = do_QueryInterface(dom); |
|
nsCOMPtr<nsIDOMWindow> opener = pdom->GetOpener(); |
|
|
|
//kmeleonDocInfo *info = kPlugin.kFuncs->GetDocInfo(hwnd); |
|
//rules.match(info->url |
|
} |
|
|
|
long DoMessage(const char *to, const char *from, const char *subject, |
|
long data1, long data2) |
|
{ |
|
if (to[0] == '*' || stricmp(to, kPlugin.dllname) == 0) { |
|
if (strcmp(subject, "Init") == 0) { |
|
Init(); |
|
} |
|
else if (strcmp(subject, "Quit") == 0) { |
|
Quit(); |
|
} |
|
else if (strcmp(subject, "Create") == 0) { |
|
Create((HWND)data1); |
|
} |
|
else if (strcmp(subject, "DoAccel") == 0) { |
|
char* accel = (char *)data1; |
|
//if (strcmp(accel, "update") == 0) |
|
// *(int *)data2 = |
|
Quit(); |
|
} |
|
else return 0; |
|
return 1; |
|
} |
|
return 0; |
|
} |
|
|
|
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { |
|
switch (ul_reason_for_call) { |
|
case DLL_PROCESS_ATTACH: |
|
case DLL_THREAD_ATTACH: |
|
case DLL_THREAD_DETACH: |
|
case DLL_PROCESS_DETACH: |
|
break; |
|
} |
|
return TRUE; |
|
} |
|
|
|
extern "C" { |
|
|
|
KMELEON_PLUGIN kmeleonPlugin *GetKmeleonPlugin() { |
|
return &kPlugin; |
|
} |
|
|
|
} |
|
|
|
|