uBlock-LLC / uBlock

uBlock: a fast, lightweight, and lean blocker for Chrome, Firefox, and Safari.
https://ublock.org/
GNU General Public License v3.0
8.19k stars 439 forks source link

Please support Firefox for Android #524

Closed stefanocaselli closed 9 years ago

stefanocaselli commented 9 years ago

Hi, please support Firefox for Android (adblock plus works on firefox for android) thanks. PS I can help with testing if needed.

gitarra commented 9 years ago

This would be great, I'd much rather use a more efficient blocker to block ads on a mobile device.

stefanocaselli commented 9 years ago

Hi, I've tried installing uBlock on Firefox for Android, but it says that version 35.0 is not supported.

alexandru commented 9 years ago

I would also like uBlock for Firefox for Android. The biggest reason I'm using Firefox on my Android is because of the availability of AdBlock Plus for it. And I've been hoping to replace it with uBlock, because performance issues on Android are far more visible than on the desktop.

Anyway, I want to thank the developers for porting uBlock to Firefox.

gorhill commented 9 years ago

It looks to me it should just be a matter of adding the proper targetApplication entry in install.rdf. However I do not have a mobile device, so I can't check whether uBlock will work just fine once made installable on mobile Firefox.

Deathamns commented 9 years ago

I know that the mobile version has more differences from the desktop forks, but the problem is that I don't have a device either where I could test.

TheReverend403 commented 9 years ago

I can confirm it doesn't work out of the box on Android with Firefox 35. It installs, but no blocking is done, and settings are inaccessible.

Related, genymotion is able to emulate android devices in virtualbox.

stefanocaselli commented 9 years ago

Hello, I can help testing. I'll try to modifiy the package and report back my experiences.

2015-01-20 16:51 GMT+01:00 Deathamns notifications@github.com:

I know that the mobile versions has more differences from the desktop forks, but the problem is that I don't have a device either where I could test.

— Reply to this email directly or view it on GitHub https://github.com/gorhill/uBlock/issues/524#issuecomment-70675788.

stefanocaselli commented 9 years ago

When I tried on my phone it didn't install ! Did you modified the package?

2015-01-20 17:19 GMT+01:00 Lee Watson notifications@github.com:

I can confirm it doesn't work out of the box on Android with Firefox 35. It installs, but no blocking is done, and settings are inaccessible.

Related, genymotion https://www.genymotion.com is able to emulate android devices in virtualbox.

— Reply to this email directly or view it on GitHub https://github.com/gorhill/uBlock/issues/524#issuecomment-70681547.

gitarra commented 9 years ago

It should be possible to use the Android emulator:

It's possible to use the Android emulator to develop add-ons for Android without access to a device, but it's slow, so for the time being it's much easier to use the technique described below.

https://developer.mozilla.org/en-US/Add-ons/SDK/Tutorials/Mobile_development

TheReverend403 commented 9 years ago

@stefanocaselli yes, modify install.rdf as gorhill said above

RandomAcronym commented 9 years ago

If you have a "spare" computer to use it with, Android-X86 will run without being slowed down by emulation.

chengsun commented 9 years ago

I've started working on this. There are a couple of places where Fennec differs from desktop Firefox internally, preventing µBlock from working in its current state.

ghost commented 9 years ago

I was able to install on mobile as well by adding the android target application, but there wasn't any blocking and there were no options available to configure or open the extension. Hopefully someone can figure it out, a lightweight blocker like this would benefit cpu usage and memory on mobile devices to save battery life

chengsun commented 9 years ago

A lot of the Firefox API for addons is subtly different for Fennec (e.g. there's no gBrowser object, the UI consists of native objects, context menus are handled differently, etc.). Hence the addon in its current state would seem to load fine, but completely fail to do anything.

Much of the conversion is mechanical (which I've done). One of the remaining issues is that I haven't yet found a working equivalent to addTabsProgressListener.

AlexVallat commented 9 years ago

From what I can tell, uBlock only uses addTabsProgressListener for onLocationChange. (TabClose and TabSelect are both available on BrowserApp.deck). Could adding a listener for the ready event on the tab itself not substitute for the progress listener, just for location change reporting?

rotanid commented 9 years ago

would be great if one of you manages to solve it, the main problem with ABP&co. with Fennec is the limitation to only one blacklist...

ncalexan commented 9 years ago

Hey folks, @ncalexan from the Fennec team here. We're happy to try to help get uBlock working in Fennec but we need a clear request. @AlexVallat says that uBlock just needs onLocationChange -- can you drop a link to the relevant code? We should be able to get you location change events somehow, some way.

chrisaljoudi commented 9 years ago

@ncalexan I think you also need to be able to observe/inspect HTTP requests: https://github.com/gorhill/uBlock/blob/master/platform/firefox/vapi-background.js#L916

marsfan commented 9 years ago

If someone could point me in the right direction as to how to write plug-ins and how uBlock works. I would love to help out, at least count me in for testing

ncalexan commented 9 years ago

This should all work fine in Fennec -- these are Gecko-level events. What's missing is the addTabsProgressListener functionality in Fennec. Since we don't use a <tabbrowser>, that interface (which just moves events around, as far as I can tell) is missing. We're thinking of what the substitute should look like.

On Wed, Feb 11, 2015 at 11:47 AM, Chris Aljoudi notifications@github.com wrote:

@ncalexan https://github.com/ncalexan I think you also need to be able to observe/inspect HTTP requests: https://github.com/gorhill/uBlock/blob/master/platform/firefox/vapi-background.js#L916

— Reply to this email directly or view it on GitHub https://github.com/gorhill/uBlock/issues/524#issuecomment-73950618.

AlexVallat commented 9 years ago

My comment was in reference to @chengsun saying that he had already completed most of the work, but that a blocking issue remaining was addTabsProgressListener.

I found that the only use of the tabs progress listener was for onLocationChange: https://github.com/gorhill/uBlock/blob/master/platform/firefox/vapi-background.js#L313 so I was starting a discussion on possible alternatives.

I don't know if there are other issues apart from that, as he hasn't replied, and does not appear to have committed any code publicly yet.

gorhill commented 9 years ago

@ncalexan,

@Deathamns is the dev to answer that kind of question, he ported uBlock to Firefox, so he should be able to answer this accurately.

chengsun commented 9 years ago

Blegh. I just noticed that I misunderstood the purpose of the onLocationChange event handler -- it only calls vAPI.tabs.onNavigation, which as far as I can tell only keeps track of page stats. (Am I right, @gorhill?) We have no way of viewing those stats on Fennec at the moment anyway, so it's irrelevant. (I did just implement listening on "DOMTitleChanged", and I think that works, but as I said, I can't really tell.)

The ads do seem to be blocked though. Give my branch a test: https://github.com/chengsun/uBlock/tree/fennec

gorhill commented 9 years ago

@chengsun

The purpose of vAPI.tabs.onNavigation is to setup an internal data structure for what is considered a new web page. It is very important, as this create the context for the page, which context is used when filters have to be evaluated.

For example, the filter ||useless.com^$domain=example.com will be evaluated as "block network requests to useless.com which originate from example.com. The context is example.com here. This context is also required for cosmetic filters to work properly.

So whatever can be done to set up this context before a page loads will be helpful.

chengsun commented 9 years ago

@gorhill: Ah, thanks for the explanation. DOMTitleChanged is fired as soon as head is parsed, according to mfinkle on IRC, so hopefully that's early enough for our purposes. Is there a website which requires such a filter that I can test on?

chrisaljoudi commented 9 years ago

@chengsun https://developer.mozilla.org/en-US/docs/Listening_to_events_on_all_tabs#onLocationChange

marsfan commented 9 years ago

How would I install it? I can't find the xpi file

Edit. Never,one, I found it

chengsun commented 9 years ago

@Marsfan: test here https://github.com/chengsun/uBlock/releases/tag/fennecWIP1 or build your own XPI in the normal way (tools/make-firefox.sh all, then look in dist/build/uBlock.firefox.xpi)

gorhill commented 9 years ago

@chengsun

Is there a website which requires such a filter that I can test on?

I found this filter in EasyList: ||amazonaws.com/ansible.js$domain=motherjones.com

So I loaded http://www.motherjones.com/, and I could see the following request being blocked: http://mj-tech.s3.amazonaws.com/ansible.js.

marsfan commented 9 years ago

@chengsun I found it, Adblock seems to work. How would I check to see of requests are blocked? @gorhill. Just try nitrome.com. Any sites with ads should show blocks, but nitrome,as I have learned, has big blank spaces were ads should be

chengsun commented 9 years ago

@gorhill: Ah thanks. Can confirm that in Fennec that request does not get blocked. I don't think the event is early enough. From what mfinkle says in IRC, this is the earliest event that we can get in Fennec at the moment, short of injecting WebProgressListeners into each tab (which is complex and has unknown performance penalties). We could stick with what we have right now, try the WebProgressListener approach, or we can file a bug with the Fennec guys so they can expose an event for us. What do you think?

chengsun commented 9 years ago

Filed Fennec bug for exposing new events here: https://bugzilla.mozilla.org/show_bug.cgi?id=1132280

my-password-is-password commented 9 years ago

@chengsun , I installed your WIP1 on my android and it blocked ||amazonaws.com/ansible.js$domain=motherjones.com and more . The page looked exactly like it did on my desktop Firefox.

ublockandroidfirefox

ublockandroidfirefox2

marsfan commented 9 years ago

@my-password-is-password how did you get the first image. I cannot find the button or any options for uBlock on Android.

my-password-is-password commented 9 years ago

@Marsfan , To get to the dev tools i typed out,

chrome://ublock/content/devtools.html

and for the dashboard,

chrome://ublock/content/dashboard.html

If you don't want to type it out you can send your self an email with those links and open it up in firefox on your phone.

marsfan commented 9 years ago

@my-password-is-password thanks.

marsfan commented 9 years ago

@my-password-is-password Why do I type chrome, isn't this firefox

my-password-is-password commented 9 years ago

@Marsfan chrome:// doesn't mean chrome browser.

https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/Tutorial/The_Chrome_URL

marsfan commented 9 years ago

go figure. I though that all Firefox internal urls were about://

chengsun commented 9 years ago

@my-password-is-password: The script gets blocked when refreshing the page (as uBlock remembers the domain name from before). However, it doesn't get blocked if you navigate to a different domain, and then back to motherjones.com again. uBlock associates the new domain name with the tab too late in the page load process. 2015-02-12-180803_1920x1080_scrot

AlexVallat commented 9 years ago

So, if I've got this straight, the issue is that when you get an "http-on-opening-request" observer notification, the information that you are given does not include the source of the request, so you don't know what tab/page it is coming from, and therefore can't selectively filter on that basis.

uBlock desktop handles this by logging tab location changes, and assuming subsequent requests belong to the tab whose location has just been changed to? (I'm not entirely clear on following the code that bit)

I did find one interesting bit of undocumented info that the channel object you get from "http-on-opening-request" does actually contain the URI of the page that's requesting it:

channel.QueryInterface(Ci.nsIHttpChannelInternal)
channel.topWindowURI

However irritatingly I have not yet been able to make that work on Android, I'm still trying to track down the equivalent of HttpChannelBase.cpp.

AlexVallat commented 9 years ago

I've done some more poking into channel, and there's an even better source of information.

channel.loadInfo.loadingDocument

This will be "chrome://browser/content/browser.xul" for the page load itself, but the page loading the resource for things loaded by a page. (loadInfo itself may also be null if it isn't for a page, for example when loading favicons)

This is an entry point for doing things like:

BrowserApp.getTabForWindow(channel.loadInfo.loadingDocument.defaultView).id

(on desktop I think the equivalent would be)

gBrowser._getTabForContentWindow(channel.loadInfo.loadingDocument.defaultView).linkedPanel

(Testing with the debugger I got an instance of BrowserApp just by Services.wm.getEnumerator('navigator:browser').getNext().BrowserApp, but I'm sure something more elegant could be arranged)

Anyway, the point being, if you can get all the info you need to construct a pageStore from the request itself, you don't need to rely on it being able to observe the location change before the request is intercepted.

gorhill commented 9 years ago

if you can get all the info you need to construct a pageStore from the request itself, you don't need to rely on it being able to observe the location change

It's actually what was happening for a long time: when the request was one of the root main_frame, the internal data structure was set-up. However, I had to change this, and rely mostly on navigation events, because issue #516. But still, if the platform-specific code of a Fennec implementation calls the core's vAPI.tabs.onNavigation when it gets such a root main_frame, it seems to me all should work fine.

AlexVallat commented 9 years ago

calls the core's vAPI.tabs.onNavigation when it gets such a root main_frame

I was thinking more that when it receives a non main_frame request, it would update the pageStore to match the main frame that request belongs to.

So adding to the detail parameter where onBeforeRequest.callback is called:

parentUrl: channel.loadInfo && channel.loadInfo.loadingDocument && channel.loadInfo.loadingDocument.URL,

then in onBeforeRequest itself, adding:

// Ensure the page store is associated with the correct parent URL
if (details.parentUrl &&
    µb.normalizePageURL(tabId, details.parentUrl) !== pageStore.pageURL) {
        vAPI.tabs.onNavigation({
            frameId: details.frameId,
            tabId: tabId,
            url: details.parentUrl
        });
}

However, maybe I'm missing something on #516. Given that he doesn't mention the values of X and Y I couldn't be sure of reproducing it. I did try #525 and #630 though, both with and without this change.

Just to try and reproduce the issue, without adding any new code I changed the 'beforeRequest' context in https://github.com/gorhill/uBlock/blob/master/src/js/traffic.js#L53 so that pageStore.reuse would get called for the main_frame, and couldn't reproduce either of #525 or #630, even with https://github.com/gorhill/uBlock/blob/master/platform/firefox/vapi-background.js#L271 commented out so the navigation event would have no effect.

So, is it worth investigating this further? If it turns out navigation events can be avoided entirely, either through allowing pageStore.reuse on main_frame or otherwise, then that would be excellent. The difficulty is ensuring no regression for the issues it was originally intended to resolve, of course!

sand-bit commented 9 years ago

Just leaving a comment... I look forward to the changes that enable fennec support eventually being merged into this repository.

desbma commented 9 years ago

would be great if one of you manages to solve it, the main problem with ABP&co. with Fennec is the limitation to only one blacklist...

+1

In addition the the "one list" limitation, ABP on Fennec also has a bug when sometimes the content that should be blocked appears and is hidden only a few seconds later (so the requests are definitely being sent).

No need to say, I am available for testing on Android if needed.

gorhill commented 9 years ago

I don't have any mobile devices, so I can't do much here.

Now, the platform-independent code should not be touched at all. Whatever quirk there is specific to Fennec should be solved solely using platform-dependent code. As said, from my remote point of view, I see it this way: if the URL of a net request is that of MAINFRAME type, and if there is a way to determine for sure that the MAINFRAME is top level, than the platform-specific code should call vAPI.tabs.onNavigation.

Touching the platform-independent code to accommodate something specific to Fennec is really not a good idea, as whatever change could destabilize all platforms. The code there has grown to address many issues over time, so changing anything in there is to be avoided.

So, is there a way for the platform-specific code in Fennec to know:

If so, it does look to me once the two conditions are met when inspecting a network request, it's a matter of calling vAPI.tabs.onNavigation callback set by the platform-independent part of uBlock.

AlexVallat commented 9 years ago

Before worrying about how to separate out any fixes between platforms, I would like to have it simply working. Then we can figure out the best way to isolate differences between browsers.

To that end, I would like to get to the bottom of why the existing platform code independent code in traffic.js and tab.js doesn't already do this for MAINFRAME requests. It does identify them, but specifically excludes them from assigning their URL to the pageStore, leaving this instead to the navigation handler (tabListener in desktop firefox, for example) to do.

In order to avoid introducing a regression, I would like to be able to isolate some steps which illustrate an issue that occurs when simply using the MAINFRAME request to assign the URL to the pageStore that is fixed by having the navigation handler assign the URL instead. That way I can repeat those steps with fixes for Fennec and validate that the solution works for the edge case that originally necessitated the navigation fix.

I will have a play around with embedded iframes, and see if that highlights anything.

gorhill commented 9 years ago

why the existing platform code independent code in traffic.js and tab.js doesn't already do this for MAINFRAME requests

Issue #516.

I am assuming such issue on Fennec would be tolerable if it allows to have uBlock working fine -- except for issue #516.

AlexVallat commented 9 years ago

So just #516, and not the others related to it? OK, so I couldn't reproduce that one exactly, not least because that file isn't available for download any more! I found another zippyshare file and could reproduce behaviour such that:

  1. On page load, uBlock reports 5 requests blocked and 4 of 7 domains connected.
  2. After clicking the Download Now button, uBlock reports 0 requests blocked and 1 domain connected.

That seems to match the issue as described, so I'm reasonably confident that if any fix for Fennec avoids that behaviour, then it isn't a regression.

So, testing that, and the motherjones.com amazonaws.com script test mentioned in earlier comments, I can confirm that fully working functionality can be achieved in Firefox without needing a navigation handler, using the code additions I mentioned in my previous post.

The question now becomes how to implement the fix so that it plays nicely with other platforms. First, though, this potentially could be made as a non-firefox specific change. Is there any reason why you can't look up the URL from the tab, given that you have the tabId for the request?

Adding to https://github.com/gorhill/uBlock/blob/master/src/js/traffic.js#L69 this platform independent code:

    // Ensure the page store is associated with the correct parent URL
    vAPI.tabs.get(tabId, function(tab) {
        if (µb.normalizePageURL(tabId, tab.url) !== pageStore.pageURL) {
            vAPI.tabs.onNavigation({
                frameId: details.frameId,
                tabId: tabId,
                url: tab.url
            });
        }
    });

appears to do the job perfectly well without needing any navigation event handers anywhere else. If there's a reason this is no good, then it probably means any firefox-specific fix based on the same idea wouldn't work too...