Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for firefox on android #1516

Merged
merged 22 commits into from
Aug 20, 2017
Merged

Added support for firefox on android #1516

merged 22 commits into from
Aug 20, 2017

Conversation

lemnis
Copy link
Contributor

@lemnis lemnis commented Jul 19, 2017

Tested in Firefox for Android 56.0a1 (2017-07-18), should work from 55+. Did check chrome and firefox desktop, didn't see anything unexpected.

See for the full conversation #1084

popup.css
:29, :30, :298; :298 fixes the issues that the overlay became wider
than the popup, as result :29 and :30 is not needed anymore and
reenables the possibility to scroll (needed on mobile)
:21 - : 30; making sure that the popup is rendered on the max width of
the device
:194; fixes a issue where the header didn’t keep the correct place when
zoomed in within firefox

options.html
:24; makes the page render on device width with the options page
(personal preference)
* add comments
* removed code that reduced the ux on other browsers
@lemnis lemnis mentioned this pull request Jul 19, 2017
@cowlicks
Copy link
Contributor

This is awesome @lemnis ! I'll test it out tomorrow.

Happened because of the remove of `overflow-y: hidden`
box-sizing: border-box;
}
@media screen and (min--moz-device-pixel-ratio:0) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

firefox specific css, otherwise the popup would render too wide

max-width: 100%;
font-size: 12px;
background: #fefefe;
color: #333;
font-family: helvetica, arial, sans-serif;
padding: 8px 15px;
width: 400px;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

creates a whitespace within chrome, use min-width instead

@cowlicks
Copy link
Contributor

@lemnis would you mind sharing your workflow for installing this on mobile? I haven't done this before.

@lemnis
Copy link
Contributor Author

lemnis commented Jul 20, 2017

  1. On your phone, open Firefox and go to about:config
  2. Change xpinstall.signature.required to true
  3. Build the app on your computer, I personally use web-ext build
  4. Change the file extension from .zip to .xpi
  5. Make the .xpi accessible from the phone, use one of the methods below:
    • Use python -m SimpleHTTPServer on your computer and open the server with your phone
    • Use adb push and open the file location on your phone
  6. For debugging, use the Firefox webIDE. All the logs will be shown within the Main Process

Remarks:

  • v55+ has a minimum support of browser_action that is needed
  • I couldn't install the extension on the current beta-build (55.0b10), got a message that the extension appears to be corrupt. Ignore this version...
  • Within FF nightly 56.0a1 theirs an issue that after install, the menu item appears 2x times or/and when you press on it, it redirects you to the "report site issue" page. If this happens force shut down the app, after a fresh start the app will behave as expected.

It's a hard life to live on the cutting edge 🙁

I don’t see the need for it and FF android doesn’t support it.
accidentally changed the width of the popup and fixed a issue where
vertical scrollbars appeared on firefox
@lemnis
Copy link
Contributor Author

lemnis commented Jul 20, 2017

All changes in src/skin/popup/css should resolve all zoom and unscrollable issues, but could create a vertical scrollbar if needed. Maybe it's best to wait for #1445

@cowlicks
Copy link
Contributor

Some extra steps I needed. After transferring the file to my device:

  • grant storage permissions to firefox
  • in firefox navigate to the url file:///mnt/sdcard this should open a file browser, select the xpi file

I'm reviewing now

@cowlicks
Copy link
Contributor

screenshot_20170720-172953

@cowlicks
Copy link
Contributor

screenshot_20170720-173756

@cowlicks
Copy link
Contributor

related to #1276 I ran the pbtest.org tests a few months ago this way and they all failed

This is great! I'll take a closer look at the changes asap. Thank you @lemnis

Copy link
Contributor

@cowlicks cowlicks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! Let me know if you have any questions about my comments.

if(!chrome.browserAction.getPopup) {
chrome.browserAction.onClicked.addListener(() => {
chrome.tabs.query({active: true, lastFocusedWindow: true}, (tabs) => {
var url = chrome.runtime.getManifest().browser_action.default_popup + "?id=" + tabs[0].id;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the "?id=" + tabs[0].id part needed?

Are we trying to find if any popup is open? In which case having the tab included might make us miss it in the url query.

src/js/popup.js Outdated
var regex = new RegExp("[?&]" + key + "(=([^&#]*)|&|#|$)"), results = regex.exec(url);
if (!results) { return null; }
if (!results[2]) { return ''; }
return decodeURIComponent(results[2].replace(/\+/g, " "));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah I see what this is for

chrome.tabs.update(popupTabs[0].id, {active: true});
chrome.tabs.reload(popupTabs[0].id);
} else {
chrome.tabs.create({url, index: tabs[0].index + 1});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can get around the passing a url parameter. After you load the popup, you could try doing:

chrome.tabs.executeScript(tabId, {code: 'getTab = callback => {callback(' + tabId + ')}'});

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would override the getTab function in popup with something that works.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I don't think that would work... Another idea is using sendMessage. But if this is working well there is no need to fix it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree there should be a neater solution, what do you think is the best behavior?

  • the current, update an existing popup with same parent tab or create a new popup
  • always create a new popup and close the popup directly after it was deactivated
  • keep at max 1 popup open and update its content

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that option 2 is the best! It also mimics the behavior of current popups (it isn't long running). And adding code for deactivating the popup should be simpler than adding the updating code for 3. And I think it will avoid the confusion a user might have when they switch to a popup, and don't know what tab the popup is for.

chrome.browserAction.setBadgeBackgroundColor({tabId: tabId, color: "#cc0000"});
}
}
if(chrome.browserAction.setBadgeText){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we move all of these if (chrome.browserAction....) { guards to the top of this function?

Also, could we combine these into a global variable like isMobile?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved feature checks.

For what would you use that global variable? All my checks are just feature checks. The best way to determine if it's mobile is chrome.runtime.getPlatformInfo((platformInfo) => {console.log(platformInfo.os)});, but i don't see a specific use case.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The use case is to isolate browser specific code into its own region so developers can reason about it more easily.

For example, I'm imagining someone might be trying to fix some bug on chrome, if they come across this code, it might not be obvious that this intended for use on mobile.

Eventually, it would nice if browser specific code was isolated to independent files, then we could have a shim API. That is out of scope for this PR. But to make it easier to do in the future, it would be nice to have browser specific pieces clearly distinguished.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re: way to determine if it is mobile

I think we should use feature existence as a way to determine if its a mobile browser, so we could do something like:

let isMobile = !(chrome.browserAction.getPopup && chrome.browserAction.setBadgeText && etc);

This also means that we won't have to consider edge cases where some of these API's may exist while others do not.

The downside is we won't immediately get new features if these api's are added. But I think think that is okay. And when they are added all we have to do is remove them from the isMobile check.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added the boolean to the badger constructor, it's only the browserAction API where it is checked against.

Added in another pull request other browser specific code 😞 , bloating the source code 😇

}
chrome.tabs.query({}, function (tabs) {
for (var i = 0; i < tabs.length; i++) {
badger.refreshIconAndContextMenu(tabs[i]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@cowlicks
Copy link
Contributor

Sorry for the delay! I left a few comments, I haven't thought of a better way to pass the id to the popup. I'll let you know if I do, but I think a URL parameter is fine for now. It might also make some selenium tests easier.

src/js/popup.js Outdated
* @return {String} Value of the key
*/
function getParameterByName(key, url) {
if (!url) { url = window.location.href; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can use the URL API to do this nicely:

getTabFromUrl(url) {
  return parseInt(new URL(url).searchParams.get('tabId'));
}

The nice thing about working on web extensions is that we only run on newer browsers, so we can use newer API's.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used that API before but didn't bother to read. Changed it know, should have read it before though 💤

@lemnis
Copy link
Contributor Author

lemnis commented Aug 14, 2017

We are both slow until nobody is unpleasantly waiting don't feel pressured to excuse yourself or keep up to a certain pace. As a Dutch girl, I'm not a 'mierenneuker' 😉

The code is updated so that a former popup will not close if the user changed the URL. I doubted if the code for onUpdated should be in his own event listener or added to to the current. I have eventually chosen the second.

As of bugzilla#1386786 is fixed, we can decide to add the number of blocked resources to the title between parenthesis. I removed the line that did set the title within this pull request background.js:765, because it was a fixed string of text.

There are 3 options:

  • Just don't bother to add the code
  • Only set a 'custom' title for FF android
  • Set a 'custom' title for every browser, so when you hover over the icon, you can read a number of blocked resources

The benefit would maybe disappear for FF mobile in the future if Mozilla decides to use icons. Also, this added information could benefit blind users, but I don't know if the current plugin is usable for them.

@@ -762,7 +768,6 @@ Badger.prototype = {
}

chrome.browserAction.setIcon({tabId: tab.id, path: iconFilename});
chrome.browserAction.setTitle({tabId: tab.id, title: "Privacy Badger"});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, now this is localized properly by the "default_title" key in the manifest

src/js/popup.js Outdated
@@ -512,6 +512,14 @@ function syncUISelections() {
* seems to be that it is synchronous.
*/
function getTab(callback) {
// Temporary fix for Firefox Android while it doesn't support `browser_action.default_popup`
if(badger.isFirefoxMobile){
chrome.tabs.query({active: true, lastFocusedWindow: true}, function(focusedTab) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can use chrome.tabs.getCurrent here instead

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getCurrent unfortunately doesn't work

@@ -776,12 +781,45 @@ function startBackgroundListeners() {
}
}, {urls: ["http://*/*", "https://*/*"]}, []);

if(badger.isFirefoxMobile) {
Copy link
Contributor

@cowlicks cowlicks Aug 15, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you refactor these to be like:

if (!isMobile) {
  startRegularListeners(); // with an exposed named function
} else {
 startMobileListeners();
}

This way the mobile logic is separate from the regular logic. So we're able to test them independently .

Copy link
Contributor

@cowlicks cowlicks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great. I've tested it, and everything is working as expected. I've just left a few notes about refactoring.

@lemnis
Copy link
Contributor Author

lemnis commented Aug 16, 2017

(Finally) moved all the code to a separate file. Maybe not the neatest code, because I am putting functions for both the popup.js and the background.js inside the same file. Besides that, feel free to change the function names, the ones that I have chosen are maybe not the best for knowing where you should use the functions.

@cowlicks
Copy link
Contributor

To fix the tests you just need to include the firefoxandroid.js file in src/tests/index.html. Otherwise LGTM

@cowlicks cowlicks merged commit 35223a3 into EFForg:master Aug 20, 2017
@cowlicks
Copy link
Contributor

@lemnis great work! Thank you.

@strugee
Copy link

strugee commented Aug 20, 2017

Does this mean that Android support is "done"/stable? Or just much closer?

Context: prism-break/prism-break#1648

@cowlicks
Copy link
Contributor

@strugee "just much closer" I think. It hasn't been tested much. And I think we should consider revamping some UI before we officially support it.

@strugee
Copy link

strugee commented Aug 21, 2017

👍 thanks for clarifying!

@ghostwords
Copy link
Member

The domain list key/legend icons seem misaligned in the popup and the options page:
screenshot from 2017-08-21 14 25 54.

This is coincidentally fixed in my WIP flexible popup layout PR (#1445) since I needed to change how the key/legend icons get rendered.

@ghostwords
Copy link
Member

It seems that we also introduced a body scrollbar in case of long-enough domain lists in Firefox:

screenshot from 2017-08-22 17 03 07

@lemnis
Copy link
Contributor Author

lemnis commented Aug 23, 2017

@ghostwords #1516 (comment) 😉

But, maybe adding temporarily body { overflow: hidden; } wouldn't be a terrible idea, it will remove the scrollbars and nobody will notice it besides the single user that already uses Privacybadger on their phone (a.k.a. me)

I overlooked the misalignment of the key/legend icons...

@cowlicks
Copy link
Contributor

@ghostwords would you mind creating a separate issue so this can be more easily tracked?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants