Replace/delete key3.db in Firefox profile from an extension - firefox

My Firefox extension needs to replace/delete key3.db in the Firefox profile, is there a way to do that? I tried to nsIFile.copyTo() but the file is not overwritten, nsIFile.remove() but it returns NS_ERROR_FILE_IS_LOCKED.

No, replacing a file while it's being used isn't a good idea. Instead you should be using the XPCOM functionality meant to manipulate this file (meaning the master password). Something like this should work:
var pk11db = Components.classes["#mozilla.org/security/pk11tokendb;1"]
.getService(Components.interfaces.nsIPK11TokenDB);
var token = pk11db.getInternalKeyToken();
token.changePassword("", "foobar");
Using "" instead of "foobar" should remove the master password. However, I'm not entirely sure that changing the master password will work without querying the current password. Firefox Mobile can be used as a relatively simple code example.

Related

How to open chrome app with specific URL through chrome_proxy.exe?

I have a Chrome app that I created with "Create Application Shortcut".
What I need is to open that app with specific url on the same domain.
Example:
chrome_proxy.exe --profile-directory=Default --app-id=xxxxxxxx "https://www.google.com"
Is that possible or any command that achive the same result?
I'm guessing you installed the Chrome app so that the website launches in a standalone window. If this is the case, you can achieve something similar by using the --app command line switch instead.
Eg: chrome_proxy.exe --profile-directory=Default --app="https://www.google.com"
This doesn't strictly open the URL in the existing app, but it does open that specific URL in a standalone window.
Here's the answer what you are looking for.
chrome_proxy.exe --profile-directory=Default --app-id=xxxxxxxx --app-launch-url-for-shortcuts-menu-item="https://youtu.be/dQw4w9WgXcQ"
Using this will work:
chrome_proxy.exe --profile-directory=Default --app-id=xxxxxxxx --app-launch-url-for-shortcuts-menu-item="https://youtu.be/dQw4w9WgXcQ"
It will launch in the special standalone window AND navigate to the specified URL.
Replace xxxxxxxx with the app id (this can be found if you look at the properties of the shortcut it created), but after you create the app this part should already be filled in.
At that point all you need to add is this part:
--app-launch-url-for-shortcuts-menu-item="https://youtu.be/dQw4w9WgXcQ"
Replacing the https:​//youtu.be/dQw4w9WgXcQ part with the full URL of where you would like to navigate to.
Documentation of the argument can be found here.
Credit due in part to 김보근.

How to avoid duplicate default configuration for Firefox add-on?

I'm trying to implement some customization for a WebExtensions add-on, but I'm running into code duplication: both the options UI script and the content script need to know the default values for each setting, and AFAIK I can't expect either of them to be run before the other. Is there an elegant way to ensure that the local storage is initialized before either of them run?
Try this. If the storage is never set, the default-value-1 and default-value-2 will be used.
let settings = await browser.storage.local.get({
option1: "default-value-1",
option2: "default-value-2"
});
See more here: https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/storage/StorageArea/get

Passing variables on the command line to a Cucumber test

I'm trying to keep usernames and passwords for a cucumber project out of version control.
Is there a way to manually pass variables on the command line like usernames and passwords to a cucumber script?
My backup plan was to put them in a YML file and add that file to the gitignore so they aren't put in version control.
So, I saw your comments with the Tin Man, and answer is Yes.
cucumber PASSWORD=my_password
PASSWORD is set as an environment variable and you can use its value by referring to it as ENV['PASSWORD']. For an example, browser.text_field(:id => 'pwd').set ENV['PASSWORD']
Another way is indirect.
What I did in past was to pass profile name and that profile will do something that I want. So, for example, I have a profile name as firefox and a firefox profile in cucumber.yml has a variable named BROWSER_TYPE with its value assigned to firefox. And this variable (BROWSER_TYPE) is used by my method that opens the browser. If its value is firefox, than this method opens firefox browser.
So, what I did here was -
Pass a profile. Name of the profile is firefox
firefox profile is defined in cucumber.yml. You can any thing with the profiles, but in this case, I define a variable named BROWSER_TYPE and assign its value as firefox.
Then I have a method that uses BROWSER_TYPE variable and uses its value to open browser.
Code for these steps -
cucumber -p firefox
My cucumber.yml file looks like
firefox: BROWSER_TYPE=firefox PLATFORM=beta
My method to open browser looks similar to -
#browser = Watir::Browser.new ENV['BROWSER_TYPE']
So, ideally you can create a profile that sets an environment variable with password, and pass that profile name to cucumber.
Two thoughts:
1) I've had the same concern, and I created some shell scripts (Mac an Unix) that store credentials in a directory off ~ that are encrypted with machine-specific passwords. I can then use "Given the credentials named blah" in my Cucumber scenarios and then use #username = testcred get #{credname} username #username = testcred get #{credname} password in my step definitions to make this work with no chance that my credentials are ever anyplace they could mistakenly get into a repo. See https://github.com/usethedata/credstore.git for where I've put this into github (early work)
2) Lastpass has a command line version that works. I've also played with sharing my test credentials with a LastPass account that's used for just test credentials. I've used the credstore stuff above to store the lastpass master password for that account (never for my real master password) and then used the lastpass command line to get the usernames and passwords. This has the advantage of when I change the credentials in Lastpass, they get updated automatically everywhere they're used

Toggle javascript support programmatically without restarting firefox

The problem: toggle javascript support without restarting firefox (nor resorting to different driver) during cucumber test run.
If Firefox's prefutils were exposed to javascript in a web page, that would make it possible. But it is not the case.
So, is there a plugin that does it? Or is there another way to solve the problem? Or is there a good tutorial (that highlights the exposing bit) on how to make such a plugin?
Edit
On a second thought, how would javascript be of any help once it is disabled? Probably the whole idea is a bit screwed.
I assume that your tests run with normal web content privileges. In that case, they aren't going to be able to affect browser settings such as whether JavaScript is enabled (I assume that's what you mean by "toggle JavaScript support").
I'd implement a simple XPCOM component with a method to turn JS support on and off (by setting the appropriate pref). You can expose it as a JavaScript global property so that your tests can access it. See Expose an XPCOM component to javascript in a web page for more details. Package your component in an extension and make sure it is installed in the Firefox instance where your tests are running.
If you want to access the preferences API directly from your content script, you can add the following prefs to Firefox, either in about:config or by adding the following lines to prefs.js in your profile directory:
user_pref("capability.principal.codebase.p1.granted", "UniversalXPConnect UniversalBrowserRead UniversalBrowserWrite UniversalPreferencesRead UniversalPreferencesWrite UniversalFileRead");
user_pref("capability.principal.codebase.p1.id", "http://www.example.com");
user_pref("capability.principal.codebase.p1.subjectName", "");`
user_pref("signed.applets.codebase_principal_support", true);
Replace www.example.com with the domain that you want to grant the privileges to. Also add this line to your JS code before you call the preferences API:
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
A local file (something loaded from file:///) is allowed to request additional privileges. Normally you would get a prompt asking whether you want to allow access - you can "auto-accept" the prompt by adding the following lines to prefs.js in the Firefox profile:
user_pref("capability.principal.codebase.p0.granted", "UniversalXPConnect");
user_pref("capability.principal.codebase.p0.id", "file://");
user_pref("capability.principal.codebase.p0.subjectName", "");
You page can then do:
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var branch = Components.classes["#mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
branch.setBoolPref("javascript.enabled", false);
This will definitely work if your page is a local file. Judging by the error message however, you are currently running code from about:blank. It might be that changing capability.principal.codebase.p0.id into about:blank or into moz-safe-about:blank will allow that page to get extended privileges as well but I am not sure.
However, none of this will really help if JavaScript is already disabled and you need to enable it. This can only be solved by writing an extension and adding it to the test profile. JavaScript in Firefox extensions works regardless of this setting.
That means you need Javascript to toggle enabling or disabling Javascript.
function setJavascriptPref(bool) {
prefs = Components.classes["#mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
prefs.setBoolPref("javascript.enabled", bool);
}

How can a bookmarklet access a Firefox extension (or vice versa)

I have written a Firefox extension that catches when a particular URL is entered and does some stuff. My main app launches Firefox with this URL. The URL contains sensitive information so I don't want it being stored in the history.
I'm concerned about the case where the extension is not installed. If its not installed and Firefox gets launched with the sensitive URL, it will get stored in history and there's nothing I can do about it. So my idea is to use a bookmarklet.
I will launch Firefox with "javascript:window.location.href='pleaseinstallthisplugin.html'; sensitiveinfo='blahblah'".
If the extension is not installed they will get redirected to a page that tells them to install it and the sensitive info won't get stored in the history. If the extension IS installed it will grab the information in the sensitiveinfo variable and do its thing.
My question is, can the bookmarklet call a method in the extension to pass the sensitive info (and if so, how) or can the extension catch when javascript is being called in the bookmarklet?
How can a bookmarklet and Firefox extension communicate?
p.s. The alternative means of getting around this situation would be for my main app to launch Firefox and communicate with the extension using sockets but I am loath to do that because I've run into too many issues over the years with users with crazy firewalls blocking socket communication. I'd like to do everything without sockets if possible.
As far as I know, bookmarklets can never access chrome files (extensions).
Bookmarklets are executed in the scope of the current document, which is almost always a content document. However, if you are passing it in via the command line, it seems to work:
/Applications/Namoroka.app/Contents/MacOS/firefox-bin javascript:alert\(Components\)
Accessing Components would throw if it was not allowed, but the alert displays the proper object.
You could use unsafeWindow to inject a global. You can add a mere property so that your bookmarklet only needs to detect whether the global is defined or not, but you should know that, as far as I know, there is no way to prohibit sites in a non-bookmarklet context from also sniffing for this same global (since it may be a privacy concern to some that sites can detect whether they are using the extension). I have confirmed in my own add-on which injects a global in a manner similar to that below that it does work in a bookmarklet as well as regular site context.
If you register an nsIObserver, e.g., where content-document-global-created is the topic, and then unwrap the subject, you can inject your global (see this if you need to inject something more sophisticated like an object with methods).
Here is some (untested) code which should do the trick:
var observerService = Cc['#mozilla.org/observer-service;1'].getService(Ci.nsIObserverService);
observerService.addObserver({observe: function (subject, topic, data) {
var unsafeWindow = XPCNativeWrapper.unwrap(subject);
unsafeWindow.myGlobal = true;
}}, 'content-document-global-created', false);
See this and this if you want an apparently easier way in an SDK add-on (not sure whether SDK postMessage communication would work as an alternative but with the apparently same concern that this would be exposed to non-bookmarklet contexts (i.e., regular websites) as well).

Resources