<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.mozilla.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Nevin</id>
	<title>MozillaWiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.mozilla.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Nevin"/>
	<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/Special:Contributions/Nevin"/>
	<updated>2026-04-16T18:03:07Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.10</generator>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Mobile/Fennec/Architecture&amp;diff=1176313</id>
		<title>Mobile/Fennec/Architecture</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Mobile/Fennec/Architecture&amp;diff=1176313"/>
		<updated>2017-07-23T07:29:34Z</updated>

		<summary type="html">&lt;p&gt;Nevin: Add some notes about Fennec architecture update.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Note: Fennec&#039;s architecture has changed and a lot of componets are moved to Java Native UI. But it&#039;s sitll nice to have a look to understand previous Fennec design :)&lt;br /&gt;
&lt;br /&gt;
==Background==&lt;br /&gt;
&lt;br /&gt;
Fennec is a XUL-based web browser designed for mobile-class devices, especially those with touchscreen support. Fennec shares much of its platform support with Firefox.  The two browsers use the exact same HTML rendering engine, as well as Add-on support, Download management, Places bookmarking &amp;amp; history, and JavaScript engine (including JIT support).&lt;br /&gt;
&lt;br /&gt;
Although the underlying platform is the same, the front-end UI is very different. Fennec is designed for smaller screens, lower CPU &amp;amp; memory specs, non-qwerty keyboards and touchscreens. Because of the large UI differences, add-ons that overlay the Firefox UI would need to be ported to work in Fennec. The focus on acceptable performance while running on mobile-class devices coupled with some of the finger-based UI features, has resulted in some unique XUL structure.&lt;br /&gt;
&lt;br /&gt;
==Application Structure==&lt;br /&gt;
&lt;br /&gt;
===Browsing===&lt;br /&gt;
&lt;br /&gt;
Fennec and Firefox are very different when it comes to the way HTML is presented. Firefox uses a &amp;lt;code&amp;gt;&amp;lt;tabbrowser&amp;gt;&amp;lt;/code&amp;gt; XUL element to create a tabbed browsing environment. The &amp;lt;code&amp;gt;&amp;lt;tabbrowser&amp;gt;&amp;lt;/code&amp;gt; is a composite control, made up of &amp;lt;code&amp;gt;&amp;lt;browser&amp;gt;&amp;lt;/code&amp;gt; elements contained inside a modified &amp;lt;code&amp;gt;&amp;lt;tabbox&amp;gt;&amp;lt;/code&amp;gt; element. Primary interaction is done through the &amp;lt;code&amp;gt;&amp;lt;browser&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Image: Mobile-typical-structure.png]]&lt;br /&gt;
&lt;br /&gt;
Fennec takes a different approach. While &amp;lt;code&amp;gt;&amp;lt;browser&amp;gt;&amp;lt;/code&amp;gt; elements are still used to render the HTML, they are hidden offscreen. The rendered HTML is drawn into a &amp;lt;code&amp;gt;&amp;lt;canvas&amp;gt;&amp;lt;/code&amp;gt; element, which acts as the primary display surface. This is primarily done for the ease in which panning and zooming can be done at acceptable levels of performance. A tabbed browsing environment is created by using an additional strip of thumbnails representing the currently opened &amp;lt;code&amp;gt;&amp;lt;browser&amp;gt;&amp;lt;/code&amp;gt; elements.&lt;br /&gt;
&lt;br /&gt;
[[Image: Mobile-fennec-structure.png]]&lt;br /&gt;
&lt;br /&gt;
The contents of the &amp;lt;code&amp;gt;&amp;lt;browser&amp;gt;&amp;lt;/code&amp;gt; is copied to the &amp;lt;code&amp;gt;&amp;lt;canvas&amp;gt;&amp;lt;/code&amp;gt;. The thumbnail used to represent the &amp;quot;tab&amp;quot; is updated either from the display &amp;lt;code&amp;gt;&amp;lt;canvas&amp;gt;&amp;lt;/code&amp;gt;, for speed, or from the &amp;lt;code&amp;gt;&amp;lt;browser&amp;gt;&amp;lt;/code&amp;gt; if the display &amp;lt;code&amp;gt;&amp;lt;canvas&amp;gt;&amp;lt;/code&amp;gt; is stale.&lt;br /&gt;
&lt;br /&gt;
Fennec uses the new [https://developer.mozilla.org/en/Gecko-Specific_DOM_Events#MozAfterPaint MozAfterPaint] event to optimize all DHTML updates to the the primary &amp;lt;code&amp;gt;&amp;lt;canvas&amp;gt;&amp;lt;/code&amp;gt; display surface. Whenever the contents of the web page changes, for whatever reason, we only update the areas that actually changed. We don’t repaint the entire surface unless it&#039;s absolutely required.&lt;br /&gt;
&lt;br /&gt;
===Chrome Elements===&lt;br /&gt;
&lt;br /&gt;
All of the primary UI elements are children of a &amp;lt;code&amp;gt;&amp;lt;stack&amp;gt;&amp;lt;/code&amp;gt;. This allows the UI elements to be absolutely positioned relative to each other, but mostly, relative to the primary &amp;lt;code&amp;gt;&amp;lt;canvas&amp;gt;&amp;lt;/code&amp;gt; display surface.&lt;br /&gt;
&lt;br /&gt;
[[Image: Mobile-fennec-stack.png]]&lt;br /&gt;
&lt;br /&gt;
Fennec uses a JavaScript helper object, WidgetStack.js, to coordinate panning the individual UI elements. WidgetStack also manages the size to the content viewport. For the most part, the left and right toolstrips are &amp;quot;glued&amp;quot; to the sides of the content display surface. Different web pages are different widths (and heights) and as the width changes, the right toolstrip moves with the growing content. This means wider web pages require more pans to get to the right toolstrip.&lt;br /&gt;
&lt;br /&gt;
Fennec tries to not use any dialogs. There are still some, used by the platform, but we are working to removing them all. Instead of dialogs, Fennec uses other UI to interact with the user. Firefox does similar things with modeless notification boxes and error pages in content.&lt;br /&gt;
&lt;br /&gt;
In those situations where a dialog or secondary window would be used, Fennec typically brings a pseudo-panel into view. Fennec does not use real &amp;lt;code&amp;gt;&amp;lt;panel&amp;gt;&amp;lt;/code&amp;gt; elements, as those tend to cause performance issues. Instead, a &amp;lt;code&amp;gt;&amp;lt;vbox&amp;gt;&amp;lt;/code&amp;gt; containing the desired UI is brought into view. The boxes are children of the &amp;lt;code&amp;gt;&amp;lt;stack&amp;gt;&amp;lt;/code&amp;gt;, can be positioned as needed, and are hidden until needed - also to improve startup performance.&lt;br /&gt;
&lt;br /&gt;
Some examples are Bookmark List, Bookmark Editor and the Tools Panel (Add-ons, Preferences and Downloads). These elements are very similar to the toolstrips, but they are not managed by the WidgetStack.&lt;br /&gt;
&lt;br /&gt;
===Panning/Zooming===&lt;br /&gt;
&lt;br /&gt;
Panning moves the entire UI, not just the content area. The toolstrips and the content move as a single entity. It should feel as though the entire browser is being moved by your finger.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;&amp;lt;canvas&amp;gt;&amp;lt;/code&amp;gt; display surface displays the visible part of the web content. However, a little more than the visible area is actually drawn into the &amp;lt;code&amp;gt;&amp;lt;canvas&amp;gt;&amp;lt;/code&amp;gt;. This allows panning to immediately show parts just &amp;quot;off screen&amp;quot; as the area moves. Also note, the entire web content is never drawn into the &amp;lt;code&amp;gt;&amp;lt;canvas&amp;gt;&amp;lt;/code&amp;gt;. That would seriously slow down performance.&lt;br /&gt;
&lt;br /&gt;
While panning moves the entire UI, zooming only affects the content area. However, the content are does &amp;quot;grow&amp;quot; when zoomed, so the right toolstrip seems farther to the right then when the content is not zoomed.&lt;br /&gt;
&lt;br /&gt;
==Performance Related Coding Guidelines==&lt;br /&gt;
&lt;br /&gt;
===Panels===&lt;br /&gt;
&lt;br /&gt;
Using &amp;lt;code&amp;gt;&amp;lt;panel&amp;gt;&amp;lt;/code&amp;gt; elements to float chrome UI over the main window leads to performance problems. In fact, any XUL element that creates a native OS window under the covers will slow things down. In Firefox, the awesomebar autocomplete list uses a &amp;lt;code&amp;gt;&amp;lt;panel&amp;gt;&amp;lt;/code&amp;gt;. The autocomplete list was re-worked such that it was a &amp;lt;code&amp;gt;&amp;lt;vbox&amp;gt;&amp;lt;/code&amp;gt; in the main &amp;lt;code&amp;gt;&amp;lt;stack&amp;gt;&amp;lt;/code&amp;gt; and the results were dramatic. The list displays much faster.&lt;br /&gt;
&lt;br /&gt;
===Showing/Hiding Elements===&lt;br /&gt;
&lt;br /&gt;
Stacking two or more elements and then toggling the visiblilty of all but one element is a simple way to create a UI that changes based on a state. While useful, this showing/hiding process can be slow. Try to avoid if possible, or find other ways to achieve the same goal.&lt;br /&gt;
&lt;br /&gt;
The URLbar in Firefox is a good example. When displaying the current web page URL, it is a &amp;lt;code&amp;gt;&amp;lt;description&amp;gt;&amp;lt;/code&amp;gt;. But when the user is typing a new URL, it is a &amp;lt;code&amp;gt;&amp;lt;textbox&amp;gt;&amp;lt;/code&amp;gt;. The process of showing/hiding the elements was taking a noticeable amount of time, affecting the perceived page loading time. In Fennec, the URLbar is always a &amp;lt;code&amp;gt;&amp;lt;textbox&amp;gt;&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;readOnly&amp;lt;/code&amp;gt; property is toggled to create the &amp;quot;caption&amp;quot; mode.&lt;br /&gt;
&lt;br /&gt;
A similar situation occurred with the favicon indicator. Fennec initially used a &amp;lt;code&amp;gt;&amp;lt;stack&amp;gt;&amp;lt;/code&amp;gt; holding two &amp;lt;code&amp;gt;&amp;lt;image&amp;gt;&amp;lt;/code&amp;gt; elements - one for the throbber and another for the website’s favicon. Again, we were showing and hiding the images depending on situation. This time it was the &amp;lt;stack&amp;gt; that was the slow down. So it was removed and page loading appeared to complete a little faster. The two image elements were kept because the load time for the swapping the favicon image with the throbber image eclipsed any benefits of removing the show/hide code.&lt;br /&gt;
&lt;br /&gt;
===Canvas and Thumbnails===&lt;br /&gt;
&lt;br /&gt;
As described above, Fennec copies the contents of a &amp;lt;code&amp;gt;&amp;lt;browser&amp;gt;&amp;lt;/code&amp;gt; to the display &amp;lt;code&amp;gt;&amp;lt;canvas&amp;gt;&amp;lt;/code&amp;gt;. Updating the contents of a browser to a canvas is not cheap on mobile devices. Each &amp;lt;code&amp;gt;drawWindow&amp;lt;/code&amp;gt; call can take ~300-400ms. On the other hand, &amp;lt;code&amp;gt;drawImage&amp;lt;/code&amp;gt; is much faster - ~100ms. Fennec uses &amp;lt;code&amp;gt;drawImage&amp;lt;/code&amp;gt; whenever possible to update the tab thumbnails.&lt;br /&gt;
&lt;br /&gt;
Fennec also uses the MozAfterPaint event to optimize all DHTML updates to the the main canvas display surface. This minimizes the amount of &amp;lt;code&amp;gt;drawWindow&amp;lt;/code&amp;gt; calls. We don&#039;t repaint the entire canvas.&lt;br /&gt;
&lt;br /&gt;
===Post-Pageload Work===&lt;br /&gt;
&lt;br /&gt;
Any work that occurs while the page is loading is potentially bad for performance. This includes any time consuming work that happens in the page &amp;quot;load&amp;quot; event handler. Users like to start interacting with page content as soon as possible. Fennec even delays updating the web page favicon until the page finishes loading.&lt;br /&gt;
&lt;br /&gt;
Fennec also had a time consuming process, converting plain text phone numbers to tel: links, that fired as soon as the page loaded. This process blocked the user from interacting with the page for a noticeable time period. The process was re-worked and became much faster. The blocking behavior was no longer noticeable and the user could interact with the page faster.&lt;br /&gt;
&lt;br /&gt;
===File I/O===&lt;br /&gt;
&lt;br /&gt;
Various places in the platform had file I/O code that was slowing Fennec down, usually on startup. Keep in mind, file I/O on mobile devices is usually measured in milliseconds. So try to avoid useless I/O whenever possible. Fennec startup improved from around 30 seconds (yes) for a first-time, cold start in Alpha 1 to around 7-10 seconds in Alpha 2.&lt;/div&gt;</summary>
		<author><name>Nevin</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Leanplum_Contextual_Hints&amp;diff=1174856</id>
		<title>Leanplum Contextual Hints</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Leanplum_Contextual_Hints&amp;diff=1174856"/>
		<updated>2017-06-30T23:16:38Z</updated>

		<summary type="html">&lt;p&gt;Nevin: Only keep important fields, and add a link to source code document.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Test Plan (iOS &amp;amp; Android) - July 2017 ==&lt;br /&gt;
; &#039;&#039;&#039;Goal:&#039;&#039;&#039;&lt;br /&gt;
With the initial implementation of the Leanplum SDK into our mobile browser products, we want to start A/B testing contextual hints to increase retention.&lt;br /&gt;
; &#039;&#039;&#039;Overarching Hypothesis:&#039;&#039;&#039;&lt;br /&gt;
We believe that by promoting contextual hints that helps users explore and change settings within the browser, we will drive DAUs and retention. &lt;br /&gt;
&lt;br /&gt;
==iOS==&lt;br /&gt;
 &lt;br /&gt;
; &#039;&#039;&#039;iOS Hypothesis 1:&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
We believe that by promoting Focus to our privacy conscious users inside Firefox, we will increase installs and DAUs in Focus, and increase retention on both apps (We know that users who have Focus and Firefox installed retain better (Adjust)).&lt;br /&gt;
 &lt;br /&gt;
; &#039;&#039;&#039;iOS Hypothesis 2:&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
We believe that by promoting Sync to our users inside Firefox, we will increase DAUs and retention as Firefox Account data shows that users with 2 synced devices retain longer. &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Hyp. # !! Message Name !! Trigger !! Targets&lt;br /&gt;
|-&lt;br /&gt;
| H1 || Clear Private Data - Focus Promotion || Clear private data || Test: en-USPost-test: en, en-gb, de, zh-tw &lt;br /&gt;
|-&lt;br /&gt;
| H1 || Opened New Tab - Focus Promotion - Promote Default Browser || Open new tab || Test: en-USPost-test: en, en-gb, de, zh-tw &lt;br /&gt;
|-&lt;br /&gt;
| H2 || Open Bookmark - Sync Promotion || Open bookmark || Test: en-USPost-test: en, en-gb, de, zh-tw&lt;br /&gt;
|-&lt;br /&gt;
| H3 || Save Bookmark - Sync Promotion || Save bookmark || Test: en-USPost-test: en, en-gb, de, zh-tw&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Android==&lt;br /&gt;
&lt;br /&gt;
; &#039;&#039;&#039;Android Hypothesis 1:&#039;&#039;&#039;&lt;br /&gt;
We believe that by prompting users to change their default browser to Firefox, we will increase DAUs and retention. &lt;br /&gt;
 &lt;br /&gt;
; &#039;&#039;&#039;Android Hypothesis 2:&#039;&#039;&#039;&lt;br /&gt;
We believe that by promoting add-ons to our users inside Firefox, we will increase DAUs and retention. &lt;br /&gt;
 &lt;br /&gt;
; &#039;&#039;&#039;Android Hypothesis 3: &#039;&#039;&#039;&lt;br /&gt;
We believe that by promoting Sync to our users inside Firefox, we will increase DAUs and retention as Firefox Account data shows that users with 2 synced devices retain longer. &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Hyp. # !! Message Name !! Trigger !! Targets &lt;br /&gt;
|-&lt;br /&gt;
| H1 || Launch Promote - Default Browser || App Start || Test: en-USPost-test: en, en-gb, en-ca, de, zh-tw inUS, CA, AU, UK, DE, TW, HK, SG &lt;br /&gt;
|-&lt;br /&gt;
| H1 || Load Bookmark - Promote Default Browser || Load bookmark || Test: en-USPost-test: en, en-gb, en-ca, de, zh-tw inUS, CA, AU, UK, DE, TW, HK, SG &lt;br /&gt;
|-&lt;br /&gt;
| H2 || Firefox launches - add-ons promotion || App start || Test: en-US Post-test: en, en-gb, en-ca, de, zh-tw in US, CA, AU, UK, DE, TW, HK, SG &lt;br /&gt;
|-&lt;br /&gt;
| H3 || Save Password - Promote Sync || Save password || Test: en-USPost-test: en, en-gb, en-ca, de, zh-tw inUS, CA, AU, UK, DE, TW, HK, SG &lt;br /&gt;
|}&lt;br /&gt;
For more detail about the triggers and deep links in Android, please go to this page[http://gecko.readthedocs.io/en/latest/mobile/android/fennec/mma.html]&lt;/div&gt;</summary>
		<author><name>Nevin</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Leanplum_Contextual_Hints&amp;diff=1174838</id>
		<title>Leanplum Contextual Hints</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Leanplum_Contextual_Hints&amp;diff=1174838"/>
		<updated>2017-06-30T17:35:26Z</updated>

		<summary type="html">&lt;p&gt;Nevin: Edit the title&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Test Plan (iOS &amp;amp; Android) - July 2017 ==&lt;br /&gt;
; &#039;&#039;&#039;Goal:&#039;&#039;&#039;&lt;br /&gt;
With the initial implementation of the Leanplum SDK into our mobile browser products, we want to start A/B testing contextual hints to increase retention.&lt;br /&gt;
; &#039;&#039;&#039;Overarching Hypothesis:&#039;&#039;&#039;&lt;br /&gt;
We believe that by promoting contextual hints that helps users explore and change settings within the browser, we will drive DAUs and retention. &lt;br /&gt;
&lt;br /&gt;
==iOS==&lt;br /&gt;
 &lt;br /&gt;
; &#039;&#039;&#039;iOS Hypothesis 1:&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
We believe that by promoting Focus to our privacy conscious users inside Firefox, we will increase installs and DAUs in Focus, and increase retention on both apps (We know that users who have Focus and Firefox installed retain better (Adjust)).&lt;br /&gt;
 &lt;br /&gt;
; &#039;&#039;&#039;iOS Hypothesis 2:&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
We believe that by promoting Sync to our users inside Firefox, we will increase DAUs and retention as Firefox Account data shows that users with 2 synced devices retain longer. &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Hyp. # !! Message Name !! Trigger !! Deep Link  !! Message Type !! Event &amp;amp; Timing !! Targets !! Result&lt;br /&gt;
|-&lt;br /&gt;
| H1 || Clear Private Data - Focus Promotion || Clear private data || Focus Adjust link || Banner || Clear Private Data once  || Test: en-USPost-test: en, en-gb, de, zh-tw || N/A&lt;br /&gt;
|-&lt;br /&gt;
| H1 || Opened New Tab - Focus Promotion - Promote Default Browser || Open new tab || Focus Adjust link || Banner || Open new tab once || Test: en-USPost-test: en, en-gb, de, zh-tw || N/A&lt;br /&gt;
|-&lt;br /&gt;
| H2 || Open Bookmark - Sync Promotion || Open bookmark || firefox://open-url?deep-link=settings/fxa || Banner || Open bookmark once || Test: en-USPost-test: en, en-gb, de, zh-tw || N/A&lt;br /&gt;
|-&lt;br /&gt;
| H3 || Save Bookmark - Sync Promotion || Save bookmark || firefox://sign_up || Dialog/Banner || Save bookmark once  || Test: en-USPost-test: en, en-gb, de, zh-tw || N/A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Android==&lt;br /&gt;
&lt;br /&gt;
; &#039;&#039;&#039;Android Hypothesis 1:&#039;&#039;&#039;&lt;br /&gt;
We believe that by prompting users to change their default browser to Firefox, we will increase DAUs and retention. &lt;br /&gt;
 &lt;br /&gt;
; &#039;&#039;&#039;Android Hypothesis 2:&#039;&#039;&#039;&lt;br /&gt;
We believe that by promoting add-ons to our users inside Firefox, we will increase DAUs and retention. &lt;br /&gt;
 &lt;br /&gt;
; &#039;&#039;&#039;Android Hypothesis 3: &#039;&#039;&#039;&lt;br /&gt;
We believe that by promoting Sync to our users inside Firefox, we will increase DAUs and retention as Firefox Account data shows that users with 2 synced devices retain longer. &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Hyp. # !! Message Name !! Trigger !! Deep Link  !! Message Type !! Event &amp;amp; Timing !! Targets !! Result&lt;br /&gt;
|-&lt;br /&gt;
| H1 || Launch Promote - Default Browser || App Start || firefox://default_browser || Dialog || User starts app second time (only once)VsUser starts app third time (only once)One event a week or 2 weeks - ask Evan || Test: en-USPost-test: en, en-gb, en-ca, de, zh-tw inUS, CA, AU, UK, DE, TW, HK, SG || N/A&lt;br /&gt;
|-&lt;br /&gt;
| H1 || Load Bookmark - Promote Default Browser || Load bookmark || firefox://default_browser || Dialog || Load Bookmark (1st time) oncevsLoad Bookmark (2 times) onceVsLoad Bookmark (5 times) once || Test: en-USPost-test: en, en-gb, en-ca, de, zh-tw inUS, CA, AU, UK, DE, TW, HK, SG || N/A&lt;br /&gt;
|-&lt;br /&gt;
| H2 || Firefox launches - add-ons promotion || App start || http://addons.mozilla.org || Dialog || User starts app 2nd time (only once)One event a week or 2 weeks || Test: en-US Post-test: en, en-gb, en-ca, de, zh-tw in US, CA, AU, UK, DE, TW, HK, SG || N/A&lt;br /&gt;
|-&lt;br /&gt;
| H3 || Save Password - Promote Sync || Save password || firefox://sign_up || Dialog/Banner || Save Password once, banner shows up the next time you launch app || Test: en-USPost-test: en, en-gb, en-ca, de, zh-tw inUS, CA, AU, UK, DE, TW, HK, SG || N/A&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Nevin</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Leanplum_Contextual_Hints&amp;diff=1174837</id>
		<title>Leanplum Contextual Hints</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Leanplum_Contextual_Hints&amp;diff=1174837"/>
		<updated>2017-06-30T17:34:30Z</updated>

		<summary type="html">&lt;p&gt;Nevin: First version for the document&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Leanplum Contextual Hints Test Plan (iOS &amp;amp; Android) - July 2017 =&lt;br /&gt;
; &#039;&#039;&#039;Goal:&#039;&#039;&#039;&lt;br /&gt;
With the initial implementation of the Leanplum SDK into our mobile browser products, we want to start A/B testing contextual hints to increase retention.&lt;br /&gt;
; &#039;&#039;&#039;Overarching Hypothesis:&#039;&#039;&#039;&lt;br /&gt;
We believe that by promoting contextual hints that helps users explore and change settings within the browser, we will drive DAUs and retention. &lt;br /&gt;
&lt;br /&gt;
==iOS==&lt;br /&gt;
 &lt;br /&gt;
; &#039;&#039;&#039;iOS Hypothesis 1:&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
We believe that by promoting Focus to our privacy conscious users inside Firefox, we will increase installs and DAUs in Focus, and increase retention on both apps (We know that users who have Focus and Firefox installed retain better (Adjust)).&lt;br /&gt;
 &lt;br /&gt;
; &#039;&#039;&#039;iOS Hypothesis 2:&#039;&#039;&#039;&lt;br /&gt;
 &lt;br /&gt;
We believe that by promoting Sync to our users inside Firefox, we will increase DAUs and retention as Firefox Account data shows that users with 2 synced devices retain longer. &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Hyp. # !! Message Name !! Trigger !! Deep Link  !! Message Type !! Event &amp;amp; Timing !! Targets !! Result&lt;br /&gt;
|-&lt;br /&gt;
| H1 || Clear Private Data - Focus Promotion || Clear private data || Focus Adjust link || Banner || Clear Private Data once  || Test: en-USPost-test: en, en-gb, de, zh-tw || N/A&lt;br /&gt;
|-&lt;br /&gt;
| H1 || Opened New Tab - Focus Promotion - Promote Default Browser || Open new tab || Focus Adjust link || Banner || Open new tab once || Test: en-USPost-test: en, en-gb, de, zh-tw || N/A&lt;br /&gt;
|-&lt;br /&gt;
| H2 || Open Bookmark - Sync Promotion || Open bookmark || firefox://open-url?deep-link=settings/fxa || Banner || Open bookmark once || Test: en-USPost-test: en, en-gb, de, zh-tw || N/A&lt;br /&gt;
|-&lt;br /&gt;
| H3 || Save Bookmark - Sync Promotion || Save bookmark || firefox://sign_up || Dialog/Banner || Save bookmark once  || Test: en-USPost-test: en, en-gb, de, zh-tw || N/A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Android==&lt;br /&gt;
&lt;br /&gt;
; &#039;&#039;&#039;Android Hypothesis 1:&#039;&#039;&#039;&lt;br /&gt;
We believe that by prompting users to change their default browser to Firefox, we will increase DAUs and retention. &lt;br /&gt;
 &lt;br /&gt;
; &#039;&#039;&#039;Android Hypothesis 2:&#039;&#039;&#039;&lt;br /&gt;
We believe that by promoting add-ons to our users inside Firefox, we will increase DAUs and retention. &lt;br /&gt;
 &lt;br /&gt;
; &#039;&#039;&#039;Android Hypothesis 3: &#039;&#039;&#039;&lt;br /&gt;
We believe that by promoting Sync to our users inside Firefox, we will increase DAUs and retention as Firefox Account data shows that users with 2 synced devices retain longer. &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Hyp. # !! Message Name !! Trigger !! Deep Link  !! Message Type !! Event &amp;amp; Timing !! Targets !! Result&lt;br /&gt;
|-&lt;br /&gt;
| H1 || Launch Promote - Default Browser || App Start || firefox://default_browser || Dialog || User starts app second time (only once)VsUser starts app third time (only once)One event a week or 2 weeks - ask Evan || Test: en-USPost-test: en, en-gb, en-ca, de, zh-tw inUS, CA, AU, UK, DE, TW, HK, SG || N/A&lt;br /&gt;
|-&lt;br /&gt;
| H1 || Load Bookmark - Promote Default Browser || Load bookmark || firefox://default_browser || Dialog || Load Bookmark (1st time) oncevsLoad Bookmark (2 times) onceVsLoad Bookmark (5 times) once || Test: en-USPost-test: en, en-gb, en-ca, de, zh-tw inUS, CA, AU, UK, DE, TW, HK, SG || N/A&lt;br /&gt;
|-&lt;br /&gt;
| H2 || Firefox launches - add-ons promotion || App start || http://addons.mozilla.org || Dialog || User starts app 2nd time (only once)One event a week or 2 weeks || Test: en-US Post-test: en, en-gb, en-ca, de, zh-tw in US, CA, AU, UK, DE, TW, HK, SG || N/A&lt;br /&gt;
|-&lt;br /&gt;
| H3 || Save Password - Promote Sync || Save password || firefox://sign_up || Dialog/Banner || Save Password once, banner shows up the next time you launch app || Test: en-USPost-test: en, en-gb, en-ca, de, zh-tw inUS, CA, AU, UK, DE, TW, HK, SG || N/A&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Nevin</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Mobile&amp;diff=1174830</id>
		<title>Mobile</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Mobile&amp;diff=1174830"/>
		<updated>2017-06-30T16:53:04Z</updated>

		<summary type="html">&lt;p&gt;Nevin: Update the document for Leanplum&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;On Mobile devices there are essentially two initiatives Firefox Mobile and FirefoxOS.&lt;br /&gt;
&lt;br /&gt;
== Firefox Mobile (Fennec)  ==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Fennec&amp;quot; is the code name of Mozilla&#039;s project to develop Firefox for mobile devices.  For more information about Firefox Mobile, see the [[Mobile/Fennec|Fennec project page]] or [[Mobile/Get_Involved|get involved page]].&lt;br /&gt;
&lt;br /&gt;
=== Goals ===&lt;br /&gt;
&lt;br /&gt;
Bringing Firefox to mobile phones is the next step towards fulfilling Mozilla’s [http://www.mozilla.org/about/mission.html mission] of providing access to one Web that everyone can access, regardless of device or location.  The overall goals for Mobile Firefox are: &lt;br /&gt;
&lt;br /&gt;
* Provide a platform for developers to create compelling content and applications using the latest Web technologies like HTML5, CSS and JavaScript.&lt;br /&gt;
* Deliver an exceptional mobile experience to users, complete with the performance, personalization and security they expect.&lt;br /&gt;
* Do all of this work in the shared Mozilla source repositories so all platforms, desktop and mobile, benefit each other.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For more background on our goals please see [[Mobile/Background|these blog posts]].  Still have questions? See our [http://www.mozilla.com/en-US/mobile/faq/ Mobile FAQ].&lt;br /&gt;
&lt;br /&gt;
== Mobile Marketing Automation ==&lt;br /&gt;
Fennec uses an external tool to help engaging with users. The tool we are using is Leanplum. For details about the running campaign, please visit [[Leanplum Contextual Hints]] page.&lt;br /&gt;
&lt;br /&gt;
== Firefox OS ==&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;[[B2G]]&amp;quot; (Boot To Gecko) is the code name of Mozilla&#039;s project to develop an OS for Mobile devices entirely based on open Web technologies.&lt;br /&gt;
* [[Gaia]] is the collection of web apps which make up the front end of [[FirefoxOS|Firefox OS]].&lt;br /&gt;
&lt;br /&gt;
== Mobile Web Compatibility ==&lt;br /&gt;
&lt;br /&gt;
Some Web sites are coding for very specific browsers. It creates [[Compatibility/Mobile|Mobile Web Compatibility]] issues for Firefox for Android and Firefox OS. You can [[Compatibility/Guide|help Mozilla]] solve these issues.&lt;/div&gt;</summary>
		<author><name>Nevin</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Mobile&amp;diff=1174829</id>
		<title>Mobile</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Mobile&amp;diff=1174829"/>
		<updated>2017-06-30T16:46:14Z</updated>

		<summary type="html">&lt;p&gt;Nevin: Create a page for Leanplum&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;On Mobile devices there are essentially two initiatives Firefox Mobile and FirefoxOS.&lt;br /&gt;
&lt;br /&gt;
== Firefox Mobile (Fennec)  ==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Fennec&amp;quot; is the code name of Mozilla&#039;s project to develop Firefox for mobile devices.  For more information about Firefox Mobile, see the [[Mobile/Fennec|Fennec project page]] or [[Mobile/Get_Involved|get involved page]].&lt;br /&gt;
&lt;br /&gt;
=== Goals ===&lt;br /&gt;
&lt;br /&gt;
Bringing Firefox to mobile phones is the next step towards fulfilling Mozilla’s [http://www.mozilla.org/about/mission.html mission] of providing access to one Web that everyone can access, regardless of device or location.  The overall goals for Mobile Firefox are: &lt;br /&gt;
&lt;br /&gt;
* Provide a platform for developers to create compelling content and applications using the latest Web technologies like HTML5, CSS and JavaScript.&lt;br /&gt;
* Deliver an exceptional mobile experience to users, complete with the performance, personalization and security they expect.&lt;br /&gt;
* Do all of this work in the shared Mozilla source repositories so all platforms, desktop and mobile, benefit each other.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
For more background on our goals please see [[Mobile/Background|these blog posts]].  Still have questions? See our [http://www.mozilla.com/en-US/mobile/faq/ Mobile FAQ].&lt;br /&gt;
&lt;br /&gt;
== Mobile Marketing Automation ==&lt;br /&gt;
Fennec uses an external tool to help engaging with users. The tool we are using is Leanplum. For details about the running campaign, please visit [[Leanplum]] page.&lt;br /&gt;
&lt;br /&gt;
== Firefox OS ==&lt;br /&gt;
&lt;br /&gt;
* &amp;quot;[[B2G]]&amp;quot; (Boot To Gecko) is the code name of Mozilla&#039;s project to develop an OS for Mobile devices entirely based on open Web technologies.&lt;br /&gt;
* [[Gaia]] is the collection of web apps which make up the front end of [[FirefoxOS|Firefox OS]].&lt;br /&gt;
&lt;br /&gt;
== Mobile Web Compatibility ==&lt;br /&gt;
&lt;br /&gt;
Some Web sites are coding for very specific browsers. It creates [[Compatibility/Mobile|Mobile Web Compatibility]] issues for Firefox for Android and Firefox OS. You can [[Compatibility/Guide|help Mozilla]] solve these issues.&lt;/div&gt;</summary>
		<author><name>Nevin</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Mobile/Fennec/Android/Switchboard&amp;diff=1172510</id>
		<title>Mobile/Fennec/Android/Switchboard</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Mobile/Fennec/Android/Switchboard&amp;diff=1172510"/>
		<updated>2017-06-02T11:28:01Z</updated>

		<summary type="html">&lt;p&gt;Nevin: Bug 1369685 -  Add a new key &amp;quot;region&amp;quot; on Switchboard&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Switchboard is a service we use to segment users for A/B testing or staged rollout of features.&lt;br /&gt;
&lt;br /&gt;
An experiment can be enabled for a specified percentage of users and limited to release channels, app versions, languages, countries (locale), device names and device manufacturers. An experiment can contain additional metadata to &amp;quot;configure&amp;quot; the experiment. This can be used to change parameters of an experiment without needing to ship a new app version. Which experiments a user is enrolled in is reported to our telemetry systems via the core ping.&lt;br /&gt;
&lt;br /&gt;
== History ==&lt;br /&gt;
&lt;br /&gt;
We started with [https://github.com/KeepSafe/Switchboard KeepSafe&#039;s Switchboard library] and server component but since then the code and architecture has changed significantly. The original implementation used a special [https://github.com/mozilla-services/switchboard-server switchboard server] that did decides which experiments a client is part of and then just returns a simplified list for the client to consume. This required the client to send data (including a unique id) to the server. To avoid this and make the administration of experiments simpler we moved to using Kinto as storage and server of the experiment configuration. Now clients load the whole configuration and decide independently what experiments they are enrolled it.&lt;br /&gt;
&lt;br /&gt;
== Summary ==&lt;br /&gt;
&lt;br /&gt;
* The experiment configuration is stored in [http://kinto.readthedocs.io/en/stable/ Kinto] and served from a CDN: https://firefox.settings.services.mozilla.com/v1/buckets/fennec/collections/experiments/records&lt;br /&gt;
* The client regularly loads the configuration (or diffs, see Kinto API) and stores it locally.&lt;br /&gt;
* Based on a UUID for bucketing the client and using the experiment filters the client decide which experiments it is part of.&lt;br /&gt;
* The experiment configuration can be modified using the Kinto web admin (VPN + account whitelisting required)&lt;br /&gt;
&lt;br /&gt;
== Adding a new experiment ==&lt;br /&gt;
&lt;br /&gt;
=== Client ===&lt;br /&gt;
&lt;br /&gt;
=== Server side ===&lt;br /&gt;
&lt;br /&gt;
* Go to https://settings-writer.prod.mozaws.net/v1/admin (You need to be on the Mozilla network, either in an office or via VPN)&lt;br /&gt;
* Login with your LDAP credentials (Your account needs to be whitelisted)&lt;br /&gt;
* Follow the Web UI to create or modify an experiment. See below for an explanation of the fields.&lt;br /&gt;
* Currently saved changes go live immediately! The Kinto team is setting up a process for a mandatory review step.&lt;br /&gt;
&lt;br /&gt;
=== Client side ===&lt;br /&gt;
&lt;br /&gt;
* Add your experiment name to [https://dxr.mozilla.org/mozilla-central/source/mobile/android/base/java/org/mozilla/gecko/Experiments.java Experiments.java]&lt;br /&gt;
* Use [https://dxr.mozilla.org/mozilla-central/source/mobile/android/base/java/org/mozilla/gecko/switchboard/SwitchBoard.java SwitchBoard.isInExperiment()] to check whether the client is part of your experiment.&lt;br /&gt;
* Use SwitchBoard.getExperimentValuesFromJson() if you have configured additional metadata for your experiment.&lt;br /&gt;
&lt;br /&gt;
=== Testing ===&lt;br /&gt;
&lt;br /&gt;
* There&#039;s an add-on that you can use for overriding the local switchboard configuration: [https://addons.mozilla.org/en-US/android/addon/switchboard-experiments/ Addon Download] [https://github.com/pocmo/Addon-Switchboard-Experiments Source code]. This works great for switching experiments on/off - but doesn&#039;t let you configure additional metadata if required by the experiment.&lt;br /&gt;
&lt;br /&gt;
== Experiment configuration ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Name&#039;&#039;&#039;: A descriptive name for the experiment. This name is used in JSON that is being sent by the server and stored by the client. Examples are:  &#039;&#039;bookmark-history-menu&#039;&#039;, &#039;&#039;malware-download-protection&#039;&#039;, &#039;&#039;promote-add-to-homescreen&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Description&#039;&#039;&#039;: A more detailed description what this experiment is about. In the best case this contains a bug number for context. Currently we send this data to the clients too (Don&#039;t make it too big).&lt;br /&gt;
* &#039;&#039;&#039;Regions&#039;&#039;&#039;: It check the country we get in the search engine manager (e.g. US, TW). If there&#039;s no value stored we just think we are not in the experiment. In the admin interface, it should be a list (e.g {&#039;US&#039;,&#039;TW&#039;} ).&lt;br /&gt;
* &#039;&#039;&#039;Buckets&#039;&#039;&#039;: Every user is in one of 100 buckets (0-99). For every experiment you can set up a min and max value (0 &amp;lt;= min &amp;lt;= max &amp;lt;= 100). The bounds are [min, max). An experiment set to buckets min=0, max=50 means that users in buckets 0-49 will have it enabled. There is no check for out of bounds values, so &amp;quot;disabled&amp;quot; experiments can have min/max buckets keys that are either out of bounds or have min == max. A disabled experiment is usually set to min=0, max=0.&lt;br /&gt;
* &#039;&#039;&#039;Filters&#039;&#039;&#039; - In addition to buckets additional filters can be used to limit the experiments to a subset of users.&lt;br /&gt;
** appId (regex): The Android app ID (e.g. org.mozilla.fennec, org.mozilla.firefox_beta, org.mozilla.firefox)&lt;br /&gt;
** version (regex): The Firefox app version number (e.g. 47.0a1&#039;, 46.0)&lt;br /&gt;
** lang (regex): Language, pulled from the default locale (e.g. eng)&lt;br /&gt;
** country (regex): Country, pulled from the default locale (e.g. USA)&lt;br /&gt;
** device (regex): Android device name&lt;br /&gt;
** manufacturer (regex): Android device manufacturer&lt;br /&gt;
* &#039;&#039;&#039;values&#039;&#039;&#039;: Every experiment can include an optional JSON object with values that are used by the experiment. For example an experiment showing a bookmark dialog after a page has been visited multiple times, could use a value that defines how many visits are needed to display the dialog. With that the experiment can change without needing to update the app.&lt;/div&gt;</summary>
		<author><name>Nevin</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Mobile/Distribution_Files&amp;diff=1167682</id>
		<title>Mobile/Distribution Files</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Mobile/Distribution_Files&amp;diff=1167682"/>
		<updated>2017-04-06T08:44:56Z</updated>

		<summary type="html">&lt;p&gt;Nevin: fix the typo and  add comma&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Like [https://wiki.mozilla.org/Distribution_INI_File desktop], mobile Firefox supplies a way for partners to repackage a set of customization files into a Firefox build without recompiling. We don&#039;t want to make custom binary builds that need to be QA&#039;d extensively. The &amp;quot;distribution files&amp;quot; concept allows a small set of external files to be used to customize a standard Firefox build. Things that can be customized include:&lt;br /&gt;
* Default bookmarks&lt;br /&gt;
* Preferences&lt;br /&gt;
* Lightweight themes&lt;br /&gt;
* Search engines&lt;br /&gt;
* Add-ons&lt;br /&gt;
* Quickshare defaults&lt;br /&gt;
* Suggested sites&lt;br /&gt;
&lt;br /&gt;
A sample distribution directory is available on [https://github.com/mozilla/fennec-distribution-sample github].&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
There are currently three ways distribution files can be ... distributed:&lt;br /&gt;
# &#039;&#039;&#039;&amp;lt;big&amp;gt;APK distributions&amp;lt;/big&amp;gt;&#039;&#039;&#039;: A folder of distribution files is repackaged into the Android APK. During the first run, those files are extracted from the APK and stored in the &amp;lt;code&amp;gt;/data/data/org.mozilla.firefox/distribution/*&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
# &#039;&#039;&#039;&amp;lt;big&amp;gt;System distributions&amp;lt;/big&amp;gt;&#039;&#039;&#039;: A folder of distribution files are shipped with the ROM image in &amp;lt;code&amp;gt;/system/org.mozilla.firefox/distribution/*&amp;lt;/code&amp;gt; directory. Shipping in this way ensures the files are not easily overwritten or removed by an application update. Note, files found in the &amp;lt;code&amp;gt;/data/data/org.mozilla.firefox/distribution/*&amp;lt;/code&amp;gt; directory will &amp;quot;win&amp;quot; in cases where both locations are used.&lt;br /&gt;
# &#039;&#039;&#039;&amp;lt;big&amp;gt;Over-the-air distributions&amp;lt;/big&amp;gt;&#039;&#039;&#039;: A distribution zip file is downloaded over-the-air as a result of a post-install referrer intent. See {{bug|1013024}}. This feature should ship with Firefox 33.&lt;br /&gt;
&lt;br /&gt;
Distributions are processed asynchronously during first run. Frontend code can chain post-distribution tasks via &amp;lt;code&amp;gt;Distribution.addOnDistributionReadyCallback&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Each type of data has its own nuances:&lt;br /&gt;
* Default bookmarks are read from the APK directly or from the &amp;quot;distribution&amp;quot; folder (if it already exists) any time a profile is created. These bookmarks are created prior to Firefox&#039;s default bookmarks.&lt;br /&gt;
* Preferences are set as &amp;quot;default&amp;quot; preferences on each run, since a &amp;quot;default&amp;quot; preference only lasts for the lifetime of the session. They are created as &amp;quot;default&amp;quot; preferences to allow &amp;quot;user&amp;quot; preferences to override them.&lt;br /&gt;
* Lightweight themes are actually just preferences. The data for the theme must live online somewhere. Typical places are the AMO theme or getpersonas.com sites.&lt;br /&gt;
* Search engine plugins and add-ons must follow a fixed folder layout.&lt;br /&gt;
* If distribution data is processed after the initial quickshare set is loaded, these options won&#039;t take effect until next run ({{bug|1021176}}).&lt;br /&gt;
&lt;br /&gt;
==Bookmarks==&lt;br /&gt;
Default bookmarks are specified in &#039;&#039;&#039;/distribution/bookmarks.json&#039;&#039;&#039;. This file should contain an array of bookmark JSON objects with the following properties:&lt;br /&gt;
* &#039;&#039;&#039;title&#039;&#039;&#039;: (required) string for the bookmark title&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: (required) string for the bookmark URL&lt;br /&gt;
* title.&amp;lt;locale&amp;gt;: (optional) title string for the given locale&lt;br /&gt;
* url.&amp;lt;locale&amp;gt;: (optional) URL string for the given locale&lt;br /&gt;
* icon: (optional) data URI for the bookmark favicon&lt;br /&gt;
* pinned: (optional) boolean for whether or not to pin this bookmark to the about:home top sites&lt;br /&gt;
** NOTE: If a bookmark is pinned, it is not visible in the Bookmarks list. Pinning only affects Tops Sites.&lt;br /&gt;
&lt;br /&gt;
Here is an example bookmarks.json:&lt;br /&gt;
 [&lt;br /&gt;
   {&lt;br /&gt;
     &amp;quot;title&amp;quot;: &amp;quot;Queso&amp;quot;,&lt;br /&gt;
     &amp;quot;url&amp;quot;: &amp;quot;http://queso.com/&amp;quot;,&lt;br /&gt;
     &amp;quot;title.en_US&amp;quot;: &amp;quot;Cheese&amp;quot;,&lt;br /&gt;
     &amp;quot;url.en_US&amp;quot;: &amp;quot;http://cheese.com&amp;quot;,&lt;br /&gt;
     &amp;quot;icon&amp;quot;: &amp;quot;data:image/png;base64,...&amp;quot;&lt;br /&gt;
   }&lt;br /&gt;
 ]&lt;br /&gt;
&lt;br /&gt;
==Preferences==&lt;br /&gt;
Preferences are specified in &#039;&#039;&#039;/distribution/preferences.json&#039;&#039;&#039;. This file should contain a JSON object with the following properties:&lt;br /&gt;
* Global&lt;br /&gt;
** &#039;&#039;&#039;id&#039;&#039;&#039;: (required) a short string unique to this distribution&lt;br /&gt;
** &#039;&#039;&#039;version&#039;&#039;&#039;: (required) version of the distribution (not the version of Firefox)&lt;br /&gt;
** &#039;&#039;&#039;about&#039;&#039;&#039;: (required) a short descriptive (ui-visible) string for this distribution&lt;br /&gt;
** about.&amp;lt;locale&amp;gt;: (optional) descriptive string for the given locale&lt;br /&gt;
* Preferences (optional)&lt;br /&gt;
** This sets default Gecko preferences for the profile (i.e. prefs that would appear in about:config)&lt;br /&gt;
* LocalizablePreferences (optional)&lt;br /&gt;
* LocalizablePreferences.&amp;lt;locale&amp;gt; (optional)&lt;br /&gt;
* ApplicationPreferences (optional)&lt;br /&gt;
** This sets as the app-scoped SharedPreferences for the entire application. Since GeckoPreferenceFragment only accept application-scoped sharedPreferences, this object will let partner also have the ability to override them. &lt;br /&gt;
* AndroidPreferences (optional)&lt;br /&gt;
** This sets Android SharedPreferences for the profile&lt;br /&gt;
&lt;br /&gt;
Here is an example preferences.json:&lt;br /&gt;
 {&lt;br /&gt;
   &amp;quot;Global&amp;quot;: {&lt;br /&gt;
     &amp;quot;id&amp;quot;: &amp;quot;testpartner&amp;quot;,&lt;br /&gt;
     &amp;quot;version&amp;quot;: 1.0,&lt;br /&gt;
     &amp;quot;about&amp;quot;: &amp;quot;Afiliado de Prueba&amp;quot;,&lt;br /&gt;
     &amp;quot;about.en-US&amp;quot;: &amp;quot;Test Partner&amp;quot;&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;Preferences&amp;quot;: {&lt;br /&gt;
     &amp;quot;distribution.test.string&amp;quot;: &amp;quot;a string pref&amp;quot;,&lt;br /&gt;
     &amp;quot;distribution.test.boolean&amp;quot;: true,&lt;br /&gt;
     &amp;quot;distribution.test.int&amp;quot;: 5&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;LocalizablePreferences&amp;quot;: {&lt;br /&gt;
     &amp;quot;distribution.test.localizeable&amp;quot;: &amp;quot;http://test.org/%LOCALE%/%LOCALE%/&amp;quot;,&lt;br /&gt;
     &amp;quot;distribution.test.localizeable-override&amp;quot;: &amp;quot;http://test.org/%LOCALE%/%LOCALE%/&amp;quot;&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;LocalizablePreferences.en-US&amp;quot;: {&lt;br /&gt;
     &amp;quot;distribution.test.localizeable-override&amp;quot;: &amp;quot;http://cheese.com&amp;quot;&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;ApplicationPreferences&amp;quot;: {&lt;br /&gt;
     &amp;quot;newtab.load_homepage&amp;quot;: &amp;quot;true&amp;quot;&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;AndroidPreferences&amp;quot;: {&lt;br /&gt;
      &amp;quot;homepage&amp;quot;: &amp;quot;http://www.mozilla.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==Lightweight Themes==&lt;br /&gt;
Lightweight themes are specified in the &amp;quot;Preferences&amp;quot; section of /distribution/preferences.json. Here is an example of the lightweight theme preferences needed for this to work:&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;Preferences&amp;quot;: {&lt;br /&gt;
   &amp;quot;lightweightThemes.isThemeSelected&amp;quot;: true,&lt;br /&gt;
   &amp;quot;lightweightThemes.persisted.footerURL&amp;quot;: false,&lt;br /&gt;
   &amp;quot;lightweightThemes.persisted.headerURL&amp;quot;: false,&lt;br /&gt;
   &amp;quot;lightweightThemes.usedThemes&amp;quot;: &amp;quot;[{\&amp;quot;id\&amp;quot;:\&amp;quot;491717\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;colored trees\&amp;quot;,\&amp;quot;headerURL\&amp;quot;:\&amp;quot;http://getpersonas-cdn.mozilla.net/static/1/7/491717/trees.png?1358076678\&amp;quot;,\&amp;quot;footerURL\&amp;quot;:\&amp;quot;http://getpersonas-cdn.mozilla.net/static/1/7/491717/trees-base.png?1358076678\&amp;quot;,\&amp;quot;textcolor\&amp;quot;:\&amp;quot;#1d022b\&amp;quot;,\&amp;quot;accentcolor\&amp;quot;:\&amp;quot;#000000\&amp;quot;,\&amp;quot;iconURL\&amp;quot;:\&amp;quot;http://getpersonas-cdn.mozilla.net/static/1/7/491717/preview_small.jpg?1358076678\&amp;quot;,\&amp;quot;previewURL\&amp;quot;:\&amp;quot;http://getpersonas-cdn.mozilla.net/static/1/7/491717/preview.jpg?1358076678\&amp;quot;,\&amp;quot;author\&amp;quot;:\&amp;quot;birdyann\&amp;quot;,\&amp;quot;description\&amp;quot;:\&amp;quot;trees arbres colored colors couleurs\&amp;quot;,\&amp;quot;updateURL\&amp;quot;:\&amp;quot;https://www.getpersonas.com/en-US/update_check/491717\&amp;quot;,\&amp;quot;version\&amp;quot;:\&amp;quot;1358076678\&amp;quot;,\&amp;quot;updateDate\&amp;quot;:1359579038207,\&amp;quot;installDate\&amp;quot;:1359579038207}]&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==Search Plugins==&lt;br /&gt;
Include search plugins in a directory structure like the following, and they will be&lt;br /&gt;
automatically loaded:&lt;br /&gt;
&lt;br /&gt;
  * distribution/&lt;br /&gt;
    * searchplugins/&lt;br /&gt;
      * common/&lt;br /&gt;
        * &amp;lt;plugin.xml&amp;gt;&lt;br /&gt;
        * &amp;lt;plugin.xml&amp;gt;&lt;br /&gt;
        * ...&lt;br /&gt;
      * locale/&lt;br /&gt;
        * &amp;lt;locale&amp;gt;/&lt;br /&gt;
          * &amp;lt;plugin.xml&amp;gt;&lt;br /&gt;
          * &amp;lt;plugin.xml&amp;gt;&lt;br /&gt;
          * ...&lt;br /&gt;
        * &amp;lt;locale&amp;gt;/&lt;br /&gt;
          * &amp;lt;plugin.xml&amp;gt;&lt;br /&gt;
          * &amp;lt;plugin.xml&amp;gt;&lt;br /&gt;
          * ...&lt;br /&gt;
&lt;br /&gt;
If a directory for the locale the browser is running in doesn&#039;t exist, Firefox will automatically try the &#039;default&#039; locale, as defined by the &amp;lt;code&amp;gt;distribution.searchplugins.defaultLocale&amp;lt;/code&amp;gt; preference.&lt;br /&gt;
&lt;br /&gt;
To set a given search engine as the default, you need to use &amp;lt;code&amp;gt;LocalizablePreferences&amp;lt;/code&amp;gt; to override the &amp;lt;code&amp;gt;browser.search.defaultenginename&amp;lt;/code&amp;gt; preference. You should also override the &amp;lt;code&amp;gt;browser.search.order.1&amp;lt;/code&amp;gt; preference to put the default engine in the right sort order. For example:&lt;br /&gt;
&lt;br /&gt;
  {&lt;br /&gt;
    ...&lt;br /&gt;
    &amp;quot;LocalizablePreferences&amp;quot;: {&lt;br /&gt;
      &amp;quot;browser.search.defaultenginename&amp;quot;: &amp;quot;&amp;lt;name-of-engine&amp;gt;&amp;quot;,&lt;br /&gt;
      &amp;quot;browser.search.order.1&amp;quot;: &amp;quot;&amp;lt;name-of-engine&amp;gt;&amp;quot;&lt;br /&gt;
      ...&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
==Add-ons==&lt;br /&gt;
Include add-ons in an extensions directory as follows, and they will be&lt;br /&gt;
automatically loaded:&lt;br /&gt;
&lt;br /&gt;
  * distribution/&lt;br /&gt;
    * extensions/&lt;br /&gt;
      * someaddon@somedomain.com.xpi&lt;br /&gt;
      * ...&lt;br /&gt;
&lt;br /&gt;
Be sure to name the add-on XPI with the ID that&#039;s specified in the add-on&#039;s install.rdf.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; As of Firefox 41, we require all add-ons to be signed through AMO, so you should make sure this XPI is signed properly before shipping in a distribution.&lt;br /&gt;
&lt;br /&gt;
==Quickshare defaults==&lt;br /&gt;
Add a file named &amp;lt;code&amp;gt;history.xml&amp;lt;/code&amp;gt; under &amp;lt;code&amp;gt;distribution/quickshare&amp;lt;/code&amp;gt;. Its contents should be something like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;historical-records&amp;gt;&lt;br /&gt;
  &amp;lt;historical-record activity=&amp;quot;com.android.mms/com.android.mms.ui.ConversationComposer&amp;quot;&lt;br /&gt;
                     time=&amp;quot;0&amp;quot;&lt;br /&gt;
                     weight=&amp;quot;1&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/historical-records&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Suggested sites==&lt;br /&gt;
Added by {{bug|1012462}} in Firefox 33.&lt;br /&gt;
&lt;br /&gt;
Use a directory tree like the following. Locales are named via a locale code, such as &amp;lt;code&amp;gt;en-US&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
  * distribution/&lt;br /&gt;
    * suggestedsites/&lt;br /&gt;
      * locales/&lt;br /&gt;
        * &amp;lt;locale&amp;gt;/&lt;br /&gt;
          * suggestedsites.json&lt;br /&gt;
      * res/&lt;br /&gt;
        * hdpi/&lt;br /&gt;
          * &amp;lt;distro&amp;gt;.png&lt;br /&gt;
        * xxhdpi/&lt;br /&gt;
          * &amp;lt;distro&amp;gt;.png&lt;br /&gt;
&lt;br /&gt;
The suggestedsites.json file should be a JSON array:&lt;br /&gt;
&lt;br /&gt;
   [&lt;br /&gt;
     {&lt;br /&gt;
       url: &amp;quot;&amp;lt;site-url&amp;gt;&amp;quot;,&lt;br /&gt;
       title: &amp;quot;&amp;lt;site-title&amp;gt;&amp;quot;,&lt;br /&gt;
       imageurl: &amp;quot;gecko.distribution://&amp;lt;image-dir&amp;gt;/&amp;lt;image-name&amp;gt;&amp;quot;,&lt;br /&gt;
       bgcolor: &amp;quot;&amp;lt;color-hex-code&amp;gt;&amp;quot;, /* &amp;quot;#FF00FF&amp;quot; with leading &#039;#&#039; */&lt;br /&gt;
       trackingid: &amp;lt;tiles-id&amp;gt; /* optional integer */&lt;br /&gt;
     },&lt;br /&gt;
     ...&lt;br /&gt;
   ]&lt;br /&gt;
&lt;br /&gt;
Where &amp;lt;code&amp;gt;&amp;lt;image-dir&amp;gt;&amp;lt;/code&amp;gt; is the directory containing the density-specific image directories (&amp;lt;code&amp;gt;mdpi&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;hdpi&amp;lt;/code&amp;gt;, etc) and &amp;lt;code&amp;gt;&amp;lt;image-name&amp;gt;&amp;lt;/code&amp;gt; is the filename under the density-specific directories without the file extension. For example, &amp;lt;code&amp;gt;gecko.distribution://suggestedsites/res/distroimage&amp;lt;/code&amp;gt; image URL will be translated to &amp;lt;code&amp;gt;&amp;lt;distribution-root-dir&amp;gt;/suggestedsites/res/xhdpi/distroimage.png&amp;lt;/code&amp;gt; on a XHDPI device.&lt;br /&gt;
&lt;br /&gt;
The list of suggested sites from the distribution will be prepended to the default list of suggested sites that ships with Firefox.&lt;br /&gt;
&lt;br /&gt;
=== Image Specs ===&lt;br /&gt;
&lt;br /&gt;
When creating images for use in Suggested Sites, please use the following guidelines. Make sure you provide images for all the DPI levels or the thumbnail may not look good on some devices:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Images Sizes (Bounds)&#039;&#039;&#039;&lt;br /&gt;
* xxhdpi: 375x195&lt;br /&gt;
* xhdpi: 250x130&lt;br /&gt;
* hdpi: 188x98&lt;br /&gt;
* mdpi:125x65&lt;br /&gt;
&lt;br /&gt;
== Testing a distribution locally ==&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: you need a clean install. If you have already run Firefox, go to settings and clear the app&#039;s data&lt;br /&gt;
&lt;br /&gt;
=== APK distribution ===&lt;br /&gt;
* To create a repackaged distribution:&lt;br /&gt;
** For &#039;&#039;&#039;Firefox for Android 45 and later&#039;&#039;&#039;:&lt;br /&gt;
*** Your distribution folder contents should be at:&lt;br /&gt;
***:&amp;lt;pre&amp;gt;/path/to/fennec-distribution-sample/assets/distribution&amp;lt;/pre&amp;gt;&lt;br /&gt;
*** Add a line like the following to your mozconfig:&lt;br /&gt;
***:&amp;lt;pre&amp;gt;ac_add_options --with-android-distribution-directory=/path/to/fennec-distribution-sample&amp;lt;/pre&amp;gt;&lt;br /&gt;
*** Make sure you have run &amp;lt;code&amp;gt;./mach configure&amp;lt;/code&amp;gt; before building and packaging&lt;br /&gt;
*** See {{bug|1163082}} for details.&lt;br /&gt;
*** &#039;&#039;&#039;Note&#039;&#039;&#039;: By default the distribution is going into the [https://gecko.readthedocs.io/en/latest/mobile/android/fennec/bouncer.html install bouncer APK]. To change that set &#039;&#039;MOZ_ANDROID_PACKAGE_INSTALL_BOUNCER&#039;&#039; to &#039;&#039;False&#039;&#039; in &#039;&#039;mobile/android/moz.configure&#039;&#039; (See {{bug|1258372}} for details) or add &#039;&#039;export MOZ_ANDROID_PACKAGE_INSTALL_BOUNCER=&#039;&#039; to mozconfig in Firefox 50 or later.&lt;br /&gt;
** For &#039;&#039;&#039;Firefox for Android 44 and earlier&#039;&#039;&#039;:&lt;br /&gt;
*** Put your distribution folder at &amp;lt;code&amp;gt;objdir/dist/bin/distribution&amp;lt;/code&amp;gt;&lt;br /&gt;
*** Run &amp;lt;code&amp;gt;./mach package&amp;lt;/code&amp;gt; to package the app&lt;br /&gt;
** When the app is launched, the distribution files will be copied out to &amp;lt;code&amp;gt;/data/data/org.mozilla.fennec_yourname/distribution&amp;lt;/code&amp;gt;, and they will override a ROM image distribution if it is present&lt;br /&gt;
&lt;br /&gt;
=== System distribution ===&lt;br /&gt;
* To create a ROM image distribution, follow these steps with a rooted phone:&lt;br /&gt;
** Copy the distribution files to a writable location&lt;br /&gt;
  adb shell mkdir /data/local/tmp/distribution&lt;br /&gt;
  adb push distribution /data/local/tmp/distribution&lt;br /&gt;
** Run &amp;lt;code&amp;gt;adb shell&amp;lt;/code&amp;gt; to get and adb shell&lt;br /&gt;
  $ su&lt;br /&gt;
  # mount&lt;br /&gt;
  # mount -o rw,remount /system&lt;br /&gt;
  # cp -r /data/local/tmp/distribution /system/&amp;lt;package&amp;gt;/  # (replace &amp;lt;package&amp;gt; with the ID for the package you want to test, e.g. org.mozilla.firefox or org.mozilla.fennec)&lt;br /&gt;
&lt;br /&gt;
==Testing distribution download==&lt;br /&gt;
A distribution download is triggered when two things are true:&lt;br /&gt;
&lt;br /&gt;
* This is the first run of Firefox (or Clear Data has been used).&lt;br /&gt;
* An &amp;lt;code&amp;gt;INSTALL_REFERRER&amp;lt;/code&amp;gt; intent has been received prior to launch.&lt;br /&gt;
&lt;br /&gt;
The Google Play app takes care of sending that intent. You can also manually send it via &amp;lt;code&amp;gt;adb shell&amp;lt;/code&amp;gt;. Assuming you&#039;re testing Nightly:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
am broadcast -a com.android.vending.INSTALL_REFERRER \&lt;br /&gt;
             -n org.mozilla.firefox/org.mozilla.gecko.distribution.ReferrerReceiver \&lt;br /&gt;
             -f 32 \&lt;br /&gt;
             --es &amp;quot;referrer&amp;quot; &amp;quot;utm_source=mozilla\&amp;amp;utm_content=testsigned\&amp;amp;utm_campaign=distribution&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will fetch the &amp;quot;testsigned.jar&amp;quot; distribution.&lt;br /&gt;
&lt;br /&gt;
(The -f 32 flag makes sure this intent is sent to stopped packages.)&lt;br /&gt;
&lt;br /&gt;
You can also do this from another Android application:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        Intent i = new Intent(&amp;quot;com.android.vending.INSTALL_REFERRER&amp;quot;);&lt;br /&gt;
        i.setPackage(&amp;quot;org.mozilla.firefox&amp;quot;);&lt;br /&gt;
        i.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);&lt;br /&gt;
        i.putExtra(&amp;quot;referrer&amp;quot;, &amp;quot;utm_source=mozilla&amp;amp;utm_content=testsigned&amp;amp;utm_campaign=distribution&amp;quot;);&lt;br /&gt;
        getContext().sendBroadcast(i);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Telemetry will be recorded for the download: &amp;lt;code&amp;gt;FENNEC_DISTRIBUTION_DOWNLOAD_TIME_MS&amp;lt;/code&amp;gt; records the download time in milliseconds, and &amp;lt;code&amp;gt;FENNEC_DISTRIBUTION_CODE_CATEGORY&amp;lt;/code&amp;gt; records the result. The value will be one of these:&lt;br /&gt;
&lt;br /&gt;
; 0: Unexpected HTTP status.&lt;br /&gt;
; 1: HTTP 1xx. Should not occur.&lt;br /&gt;
; 2: HTTP 2xx. The expected result.&lt;br /&gt;
; 3: HTTP 3xx. Should not occur.&lt;br /&gt;
; 4: HTTP 4xx. Should not occur.&lt;br /&gt;
; 5: HTTP 5xx. Should not occur.&lt;br /&gt;
; 6: The device was offline.&lt;br /&gt;
; 7: Generic fetch exception.&lt;br /&gt;
; 8: Failure during processing of downloaded zip.&lt;br /&gt;
; 9: Security exception: malformed, corrupted, or modified signatures.&lt;br /&gt;
; 10: Malformed distribution file.&lt;br /&gt;
; 11: Fetch: socket error.&lt;br /&gt;
; 12: Fetch: SSL error.&lt;br /&gt;
; 13: Fetch: non-success HTTP response.&lt;br /&gt;
; 14: Fetch: invalid Content-Type header received.&lt;br /&gt;
&lt;br /&gt;
==Crafting a distribution referrer==&lt;br /&gt;
&lt;br /&gt;
These are the fields exposed in a referrer URL to Play:&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;code&amp;gt;utm_content&amp;lt;/code&amp;gt;: &#039;&#039;&#039;The distribution name&#039;&#039;&#039;. Must be unique. Identifies the distribution name.&lt;br /&gt;
; &amp;lt;code&amp;gt;utm_campaign&amp;lt;/code&amp;gt;: &#039;&#039;&#039;The campaign name&#039;&#039;&#039;. Must be &amp;lt;code&amp;gt;distribution&amp;lt;/code&amp;gt;.&lt;br /&gt;
; &amp;lt;code&amp;gt;utm_source&amp;lt;/code&amp;gt;: Original referrer. Must be &amp;lt;code&amp;gt;mozilla&amp;lt;/code&amp;gt; for both downloadable distributions and campaign tracking.&lt;br /&gt;
; &amp;lt;code&amp;gt;utm_medium&amp;lt;/code&amp;gt;: Campaign medium. E.g., &amp;lt;code&amp;gt;email&amp;lt;/code&amp;gt;. Not used by Firefox.&lt;br /&gt;
; &amp;lt;code&amp;gt;utm_term&amp;lt;/code&amp;gt;: Search terms. E.g., &amp;lt;code&amp;gt;web+browser&amp;lt;/code&amp;gt;. Not used by Firefox.&lt;br /&gt;
&lt;br /&gt;
== Distribution bundles ==&lt;br /&gt;
&lt;br /&gt;
Firefox for Android 46.0 introduced support for distribution bundles based on the &#039;&#039;&#039;MCC&#039;&#039;&#039; (mobile country code, [https://en.wikipedia.org/wiki/Mobile_country_code]) and &#039;&#039;&#039;MNC&#039;&#039;&#039; (mobile network code) codes of the inserted SIM card. Instead of the default distribution directory Firefox will search a distribution in the following sub directories first:&lt;br /&gt;
* (distribution directory)/&#039;&#039;&amp;lt;MCC&amp;gt;&#039;&#039;/&#039;&#039;&amp;lt;MNC&amp;gt;&#039;&#039; - For bundled distributions for specific network providers&lt;br /&gt;
* (distribution directory)/&#039;&#039;&amp;lt;MCC&amp;gt;&#039;&#039; - For bundled distributions for specific countries&lt;br /&gt;
* (distribution directory)/&#039;&#039;default&#039;&#039; - For bundled distributions with no matching MCC/MNC&lt;br /&gt;
&lt;br /&gt;
=== Example distribution bundle ===&lt;br /&gt;
  distribution&lt;br /&gt;
  ├── 208                           // 208 = Country code of France&lt;br /&gt;
  │   └── bookmarks.json            // Bookmarks just for users with a SIM card of a French operator&lt;br /&gt;
  ├── 262                           // 262 = Country code of Germany&lt;br /&gt;
  │   └── 01                        // 01 = Network code of &amp;quot;Deutsche Telekom&amp;quot;&lt;br /&gt;
  │       ├── bookmarks.json        // Bookmarks..&lt;br /&gt;
  │       └── preferences.json      // ... and preferences just for users of a SIM card of &amp;quot;Deutsche Telekom&amp;quot;&lt;br /&gt;
  └── default                       // Default folder&lt;br /&gt;
      └── preferences.json          // Preferences for all users with different SIM cards.&lt;br /&gt;
&lt;br /&gt;
== Partner Content Providers ==&lt;br /&gt;
&lt;br /&gt;
Android system images can ship with two content providers to customize installed browsers:&lt;br /&gt;
* content://com.android.partnerbookmarks - For partner bookmarks&lt;br /&gt;
* content://com.android.partnerbrowsercustomizations - For customizations (Details see below)&lt;br /&gt;
&lt;br /&gt;
Firefox for Android supports reading data from both of those content providers (Starting with Firefox for Android 50.0) if this has been enabled by a distribution. If the following preferences are not written by a distribution then Firefox for Android will ignore the data from the partner content providers.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;/distribution/preferences.json:&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[..]&lt;br /&gt;
  &amp;quot;AndroidPreferences&amp;quot;: {&lt;br /&gt;
    &amp;quot;distribution.read_partner_bookmarks_provider&amp;quot;: true,&lt;br /&gt;
    &amp;quot;distribution.read_partner_customizations_provider&amp;quot;: true&lt;br /&gt;
  }&lt;br /&gt;
[..]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bookmarks Content Provider ===&lt;br /&gt;
&lt;br /&gt;
Firefox for Android (&amp;gt;= 50.0) supports reading bookmarks and folders from the content provider. Reading icons from the content provider is currently not supported (See {{bug|1286203}}). Editing and deleting bookmarks/folders is not supported yet but planned.&lt;br /&gt;
&lt;br /&gt;
An example implementation of the content provider can be found in the official Android source tree:&lt;br /&gt;
* https://android.googlesource.com/platform/packages/providers/PartnerBookmarksProvider/+/master/src/com/android/providers/partnerbookmarks/PartnerBookmarksProvider.java&lt;br /&gt;
&lt;br /&gt;
=== Customizations Content Provider ===&lt;br /&gt;
&lt;br /&gt;
Firefox for Android (&amp;gt;= 50.0) only supports reading the &#039;homepage&#039; from the content provider. All other values are ignored.&lt;br /&gt;
&lt;br /&gt;
content://com.android.partnerbrowsercustomizations&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Path !! Column !! Supported&lt;br /&gt;
|-&lt;br /&gt;
| /homepage || homepage || Yes&lt;br /&gt;
|-&lt;br /&gt;
| /disableincognitomode || disableincognitomode || No&lt;br /&gt;
|-&lt;br /&gt;
| /disablebookmarksediting || disablebookmarksediting || No&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Testing ===&lt;br /&gt;
&lt;br /&gt;
There&#039;s a test app with sample data available on GitHub:&lt;br /&gt;
* https://github.com/pocmo/BrowserPartner&lt;br /&gt;
&lt;br /&gt;
The test app uses slightly different content provider authorities to allow being installed on devices that already ship with partner content providers:&lt;br /&gt;
&lt;br /&gt;
* com.android.partnerbookmarks.&#039;&#039;&#039;&#039;&#039;test&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
* com.android.partnerbrowsercustomizations.&#039;&#039;&#039;&#039;&#039;test&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A custom Firefox build is required to read from the test content providers.&lt;/div&gt;</summary>
		<author><name>Nevin</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Mobile/Distribution_Files&amp;diff=1167681</id>
		<title>Mobile/Distribution Files</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Mobile/Distribution_Files&amp;diff=1167681"/>
		<updated>2017-04-06T08:39:23Z</updated>

		<summary type="html">&lt;p&gt;Nevin: Bug 1293713 - update the pref name&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Like [https://wiki.mozilla.org/Distribution_INI_File desktop], mobile Firefox supplies a way for partners to repackage a set of customization files into a Firefox build without recompiling. We don&#039;t want to make custom binary builds that need to be QA&#039;d extensively. The &amp;quot;distribution files&amp;quot; concept allows a small set of external files to be used to customize a standard Firefox build. Things that can be customized include:&lt;br /&gt;
* Default bookmarks&lt;br /&gt;
* Preferences&lt;br /&gt;
* Lightweight themes&lt;br /&gt;
* Search engines&lt;br /&gt;
* Add-ons&lt;br /&gt;
* Quickshare defaults&lt;br /&gt;
* Suggested sites&lt;br /&gt;
&lt;br /&gt;
A sample distribution directory is available on [https://github.com/mozilla/fennec-distribution-sample github].&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
There are currently three ways distribution files can be ... distributed:&lt;br /&gt;
# &#039;&#039;&#039;&amp;lt;big&amp;gt;APK distributions&amp;lt;/big&amp;gt;&#039;&#039;&#039;: A folder of distribution files is repackaged into the Android APK. During the first run, those files are extracted from the APK and stored in the &amp;lt;code&amp;gt;/data/data/org.mozilla.firefox/distribution/*&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
# &#039;&#039;&#039;&amp;lt;big&amp;gt;System distributions&amp;lt;/big&amp;gt;&#039;&#039;&#039;: A folder of distribution files are shipped with the ROM image in &amp;lt;code&amp;gt;/system/org.mozilla.firefox/distribution/*&amp;lt;/code&amp;gt; directory. Shipping in this way ensures the files are not easily overwritten or removed by an application update. Note, files found in the &amp;lt;code&amp;gt;/data/data/org.mozilla.firefox/distribution/*&amp;lt;/code&amp;gt; directory will &amp;quot;win&amp;quot; in cases where both locations are used.&lt;br /&gt;
# &#039;&#039;&#039;&amp;lt;big&amp;gt;Over-the-air distributions&amp;lt;/big&amp;gt;&#039;&#039;&#039;: A distribution zip file is downloaded over-the-air as a result of a post-install referrer intent. See {{bug|1013024}}. This feature should ship with Firefox 33.&lt;br /&gt;
&lt;br /&gt;
Distributions are processed asynchronously during first run. Frontend code can chain post-distribution tasks via &amp;lt;code&amp;gt;Distribution.addOnDistributionReadyCallback&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Each type of data has its own nuances:&lt;br /&gt;
* Default bookmarks are read from the APK directly or from the &amp;quot;distribution&amp;quot; folder (if it already exists) any time a profile is created. These bookmarks are created prior to Firefox&#039;s default bookmarks.&lt;br /&gt;
* Preferences are set as &amp;quot;default&amp;quot; preferences on each run, since a &amp;quot;default&amp;quot; preference only lasts for the lifetime of the session. They are created as &amp;quot;default&amp;quot; preferences to allow &amp;quot;user&amp;quot; preferences to override them.&lt;br /&gt;
* Lightweight themes are actually just preferences. The data for the theme must live online somewhere. Typical places are the AMO theme or getpersonas.com sites.&lt;br /&gt;
* Search engine plugins and add-ons must follow a fixed folder layout.&lt;br /&gt;
* If distribution data is processed after the initial quickshare set is loaded, these options won&#039;t take effect until next run ({{bug|1021176}}).&lt;br /&gt;
&lt;br /&gt;
==Bookmarks==&lt;br /&gt;
Default bookmarks are specified in &#039;&#039;&#039;/distribution/bookmarks.json&#039;&#039;&#039;. This file should contain an array of bookmark JSON objects with the following properties:&lt;br /&gt;
* &#039;&#039;&#039;title&#039;&#039;&#039;: (required) string for the bookmark title&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: (required) string for the bookmark URL&lt;br /&gt;
* title.&amp;lt;locale&amp;gt;: (optional) title string for the given locale&lt;br /&gt;
* url.&amp;lt;locale&amp;gt;: (optional) URL string for the given locale&lt;br /&gt;
* icon: (optional) data URI for the bookmark favicon&lt;br /&gt;
* pinned: (optional) boolean for whether or not to pin this bookmark to the about:home top sites&lt;br /&gt;
** NOTE: If a bookmark is pinned, it is not visible in the Bookmarks list. Pinning only affects Tops Sites.&lt;br /&gt;
&lt;br /&gt;
Here is an example bookmarks.json:&lt;br /&gt;
 [&lt;br /&gt;
   {&lt;br /&gt;
     &amp;quot;title&amp;quot;: &amp;quot;Queso&amp;quot;,&lt;br /&gt;
     &amp;quot;url&amp;quot;: &amp;quot;http://queso.com/&amp;quot;,&lt;br /&gt;
     &amp;quot;title.en_US&amp;quot;: &amp;quot;Cheese&amp;quot;,&lt;br /&gt;
     &amp;quot;url.en_US&amp;quot;: &amp;quot;http://cheese.com&amp;quot;,&lt;br /&gt;
     &amp;quot;icon&amp;quot;: &amp;quot;data:image/png;base64,...&amp;quot;&lt;br /&gt;
   }&lt;br /&gt;
 ]&lt;br /&gt;
&lt;br /&gt;
==Preferences==&lt;br /&gt;
Preferences are specified in &#039;&#039;&#039;/distribution/preferences.json&#039;&#039;&#039;. This file should contain a JSON object with the following properties:&lt;br /&gt;
* Global&lt;br /&gt;
** &#039;&#039;&#039;id&#039;&#039;&#039;: (required) a short string unique to this distribution&lt;br /&gt;
** &#039;&#039;&#039;version&#039;&#039;&#039;: (required) version of the distribution (not the version of Firefox)&lt;br /&gt;
** &#039;&#039;&#039;about&#039;&#039;&#039;: (required) a short descriptive (ui-visible) string for this distribution&lt;br /&gt;
** about.&amp;lt;locale&amp;gt;: (optional) descriptive string for the given locale&lt;br /&gt;
* Preferences (optional)&lt;br /&gt;
** This sets default Gecko preferences for the profile (i.e. prefs that would appear in about:config)&lt;br /&gt;
* LocalizablePreferences (optional)&lt;br /&gt;
* LocalizablePreferences.&amp;lt;locale&amp;gt; (optional)&lt;br /&gt;
* ApplicationPreferences (optional)&lt;br /&gt;
** This sets as the app-scoped SharedPreferences for the entire application. Since GeckoPreferenceFragment only accept application-scoped sharedPreferences, this object will let partner also have the ability to override them. &lt;br /&gt;
* AndroidPreferences (optional)&lt;br /&gt;
** This sets Android SharedPreferences for the profile&lt;br /&gt;
&lt;br /&gt;
Here is an example preferences.json:&lt;br /&gt;
 {&lt;br /&gt;
   &amp;quot;Global&amp;quot;: {&lt;br /&gt;
     &amp;quot;id&amp;quot;: &amp;quot;testpartner&amp;quot;,&lt;br /&gt;
     &amp;quot;version&amp;quot;: 1.0,&lt;br /&gt;
     &amp;quot;about&amp;quot;: &amp;quot;Afiliado de Prueba&amp;quot;,&lt;br /&gt;
     &amp;quot;about.en-US&amp;quot;: &amp;quot;Test Partner&amp;quot;&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;Preferences&amp;quot;: {&lt;br /&gt;
     &amp;quot;distribution.test.string&amp;quot;: &amp;quot;a string pref&amp;quot;,&lt;br /&gt;
     &amp;quot;distribution.test.boolean&amp;quot;: true,&lt;br /&gt;
     &amp;quot;distribution.test.int&amp;quot;: 5&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;LocalizablePreferences&amp;quot;: {&lt;br /&gt;
     &amp;quot;distribution.test.localizeable&amp;quot;: &amp;quot;http://test.org/%LOCALE%/%LOCALE%/&amp;quot;,&lt;br /&gt;
     &amp;quot;distribution.test.localizeable-override&amp;quot;: &amp;quot;http://test.org/%LOCALE%/%LOCALE%/&amp;quot;&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;LocalizablePreferences.en-US&amp;quot;: {&lt;br /&gt;
     &amp;quot;distribution.test.localizeable-override&amp;quot;: &amp;quot;http://cheese.com&amp;quot;&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;AnpplicationPreferences&amp;quot;: {&lt;br /&gt;
     &amp;quot;newtab.load_homepage&amp;quot;: &amp;quot;true&amp;quot;&lt;br /&gt;
   }&lt;br /&gt;
   &amp;quot;AndroidPreferences&amp;quot;: {&lt;br /&gt;
      &amp;quot;homepage&amp;quot;: &amp;quot;http://www.mozilla.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==Lightweight Themes==&lt;br /&gt;
Lightweight themes are specified in the &amp;quot;Preferences&amp;quot; section of /distribution/preferences.json. Here is an example of the lightweight theme preferences needed for this to work:&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;Preferences&amp;quot;: {&lt;br /&gt;
   &amp;quot;lightweightThemes.isThemeSelected&amp;quot;: true,&lt;br /&gt;
   &amp;quot;lightweightThemes.persisted.footerURL&amp;quot;: false,&lt;br /&gt;
   &amp;quot;lightweightThemes.persisted.headerURL&amp;quot;: false,&lt;br /&gt;
   &amp;quot;lightweightThemes.usedThemes&amp;quot;: &amp;quot;[{\&amp;quot;id\&amp;quot;:\&amp;quot;491717\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;colored trees\&amp;quot;,\&amp;quot;headerURL\&amp;quot;:\&amp;quot;http://getpersonas-cdn.mozilla.net/static/1/7/491717/trees.png?1358076678\&amp;quot;,\&amp;quot;footerURL\&amp;quot;:\&amp;quot;http://getpersonas-cdn.mozilla.net/static/1/7/491717/trees-base.png?1358076678\&amp;quot;,\&amp;quot;textcolor\&amp;quot;:\&amp;quot;#1d022b\&amp;quot;,\&amp;quot;accentcolor\&amp;quot;:\&amp;quot;#000000\&amp;quot;,\&amp;quot;iconURL\&amp;quot;:\&amp;quot;http://getpersonas-cdn.mozilla.net/static/1/7/491717/preview_small.jpg?1358076678\&amp;quot;,\&amp;quot;previewURL\&amp;quot;:\&amp;quot;http://getpersonas-cdn.mozilla.net/static/1/7/491717/preview.jpg?1358076678\&amp;quot;,\&amp;quot;author\&amp;quot;:\&amp;quot;birdyann\&amp;quot;,\&amp;quot;description\&amp;quot;:\&amp;quot;trees arbres colored colors couleurs\&amp;quot;,\&amp;quot;updateURL\&amp;quot;:\&amp;quot;https://www.getpersonas.com/en-US/update_check/491717\&amp;quot;,\&amp;quot;version\&amp;quot;:\&amp;quot;1358076678\&amp;quot;,\&amp;quot;updateDate\&amp;quot;:1359579038207,\&amp;quot;installDate\&amp;quot;:1359579038207}]&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==Search Plugins==&lt;br /&gt;
Include search plugins in a directory structure like the following, and they will be&lt;br /&gt;
automatically loaded:&lt;br /&gt;
&lt;br /&gt;
  * distribution/&lt;br /&gt;
    * searchplugins/&lt;br /&gt;
      * common/&lt;br /&gt;
        * &amp;lt;plugin.xml&amp;gt;&lt;br /&gt;
        * &amp;lt;plugin.xml&amp;gt;&lt;br /&gt;
        * ...&lt;br /&gt;
      * locale/&lt;br /&gt;
        * &amp;lt;locale&amp;gt;/&lt;br /&gt;
          * &amp;lt;plugin.xml&amp;gt;&lt;br /&gt;
          * &amp;lt;plugin.xml&amp;gt;&lt;br /&gt;
          * ...&lt;br /&gt;
        * &amp;lt;locale&amp;gt;/&lt;br /&gt;
          * &amp;lt;plugin.xml&amp;gt;&lt;br /&gt;
          * &amp;lt;plugin.xml&amp;gt;&lt;br /&gt;
          * ...&lt;br /&gt;
&lt;br /&gt;
If a directory for the locale the browser is running in doesn&#039;t exist, Firefox will automatically try the &#039;default&#039; locale, as defined by the &amp;lt;code&amp;gt;distribution.searchplugins.defaultLocale&amp;lt;/code&amp;gt; preference.&lt;br /&gt;
&lt;br /&gt;
To set a given search engine as the default, you need to use &amp;lt;code&amp;gt;LocalizablePreferences&amp;lt;/code&amp;gt; to override the &amp;lt;code&amp;gt;browser.search.defaultenginename&amp;lt;/code&amp;gt; preference. You should also override the &amp;lt;code&amp;gt;browser.search.order.1&amp;lt;/code&amp;gt; preference to put the default engine in the right sort order. For example:&lt;br /&gt;
&lt;br /&gt;
  {&lt;br /&gt;
    ...&lt;br /&gt;
    &amp;quot;LocalizablePreferences&amp;quot;: {&lt;br /&gt;
      &amp;quot;browser.search.defaultenginename&amp;quot;: &amp;quot;&amp;lt;name-of-engine&amp;gt;&amp;quot;,&lt;br /&gt;
      &amp;quot;browser.search.order.1&amp;quot;: &amp;quot;&amp;lt;name-of-engine&amp;gt;&amp;quot;&lt;br /&gt;
      ...&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
==Add-ons==&lt;br /&gt;
Include add-ons in an extensions directory as follows, and they will be&lt;br /&gt;
automatically loaded:&lt;br /&gt;
&lt;br /&gt;
  * distribution/&lt;br /&gt;
    * extensions/&lt;br /&gt;
      * someaddon@somedomain.com.xpi&lt;br /&gt;
      * ...&lt;br /&gt;
&lt;br /&gt;
Be sure to name the add-on XPI with the ID that&#039;s specified in the add-on&#039;s install.rdf.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; As of Firefox 41, we require all add-ons to be signed through AMO, so you should make sure this XPI is signed properly before shipping in a distribution.&lt;br /&gt;
&lt;br /&gt;
==Quickshare defaults==&lt;br /&gt;
Add a file named &amp;lt;code&amp;gt;history.xml&amp;lt;/code&amp;gt; under &amp;lt;code&amp;gt;distribution/quickshare&amp;lt;/code&amp;gt;. Its contents should be something like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;historical-records&amp;gt;&lt;br /&gt;
  &amp;lt;historical-record activity=&amp;quot;com.android.mms/com.android.mms.ui.ConversationComposer&amp;quot;&lt;br /&gt;
                     time=&amp;quot;0&amp;quot;&lt;br /&gt;
                     weight=&amp;quot;1&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/historical-records&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Suggested sites==&lt;br /&gt;
Added by {{bug|1012462}} in Firefox 33.&lt;br /&gt;
&lt;br /&gt;
Use a directory tree like the following. Locales are named via a locale code, such as &amp;lt;code&amp;gt;en-US&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
  * distribution/&lt;br /&gt;
    * suggestedsites/&lt;br /&gt;
      * locales/&lt;br /&gt;
        * &amp;lt;locale&amp;gt;/&lt;br /&gt;
          * suggestedsites.json&lt;br /&gt;
      * res/&lt;br /&gt;
        * hdpi/&lt;br /&gt;
          * &amp;lt;distro&amp;gt;.png&lt;br /&gt;
        * xxhdpi/&lt;br /&gt;
          * &amp;lt;distro&amp;gt;.png&lt;br /&gt;
&lt;br /&gt;
The suggestedsites.json file should be a JSON array:&lt;br /&gt;
&lt;br /&gt;
   [&lt;br /&gt;
     {&lt;br /&gt;
       url: &amp;quot;&amp;lt;site-url&amp;gt;&amp;quot;,&lt;br /&gt;
       title: &amp;quot;&amp;lt;site-title&amp;gt;&amp;quot;,&lt;br /&gt;
       imageurl: &amp;quot;gecko.distribution://&amp;lt;image-dir&amp;gt;/&amp;lt;image-name&amp;gt;&amp;quot;,&lt;br /&gt;
       bgcolor: &amp;quot;&amp;lt;color-hex-code&amp;gt;&amp;quot;, /* &amp;quot;#FF00FF&amp;quot; with leading &#039;#&#039; */&lt;br /&gt;
       trackingid: &amp;lt;tiles-id&amp;gt; /* optional integer */&lt;br /&gt;
     },&lt;br /&gt;
     ...&lt;br /&gt;
   ]&lt;br /&gt;
&lt;br /&gt;
Where &amp;lt;code&amp;gt;&amp;lt;image-dir&amp;gt;&amp;lt;/code&amp;gt; is the directory containing the density-specific image directories (&amp;lt;code&amp;gt;mdpi&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;hdpi&amp;lt;/code&amp;gt;, etc) and &amp;lt;code&amp;gt;&amp;lt;image-name&amp;gt;&amp;lt;/code&amp;gt; is the filename under the density-specific directories without the file extension. For example, &amp;lt;code&amp;gt;gecko.distribution://suggestedsites/res/distroimage&amp;lt;/code&amp;gt; image URL will be translated to &amp;lt;code&amp;gt;&amp;lt;distribution-root-dir&amp;gt;/suggestedsites/res/xhdpi/distroimage.png&amp;lt;/code&amp;gt; on a XHDPI device.&lt;br /&gt;
&lt;br /&gt;
The list of suggested sites from the distribution will be prepended to the default list of suggested sites that ships with Firefox.&lt;br /&gt;
&lt;br /&gt;
=== Image Specs ===&lt;br /&gt;
&lt;br /&gt;
When creating images for use in Suggested Sites, please use the following guidelines. Make sure you provide images for all the DPI levels or the thumbnail may not look good on some devices:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Images Sizes (Bounds)&#039;&#039;&#039;&lt;br /&gt;
* xxhdpi: 375x195&lt;br /&gt;
* xhdpi: 250x130&lt;br /&gt;
* hdpi: 188x98&lt;br /&gt;
* mdpi:125x65&lt;br /&gt;
&lt;br /&gt;
== Testing a distribution locally ==&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: you need a clean install. If you have already run Firefox, go to settings and clear the app&#039;s data&lt;br /&gt;
&lt;br /&gt;
=== APK distribution ===&lt;br /&gt;
* To create a repackaged distribution:&lt;br /&gt;
** For &#039;&#039;&#039;Firefox for Android 45 and later&#039;&#039;&#039;:&lt;br /&gt;
*** Your distribution folder contents should be at:&lt;br /&gt;
***:&amp;lt;pre&amp;gt;/path/to/fennec-distribution-sample/assets/distribution&amp;lt;/pre&amp;gt;&lt;br /&gt;
*** Add a line like the following to your mozconfig:&lt;br /&gt;
***:&amp;lt;pre&amp;gt;ac_add_options --with-android-distribution-directory=/path/to/fennec-distribution-sample&amp;lt;/pre&amp;gt;&lt;br /&gt;
*** Make sure you have run &amp;lt;code&amp;gt;./mach configure&amp;lt;/code&amp;gt; before building and packaging&lt;br /&gt;
*** See {{bug|1163082}} for details.&lt;br /&gt;
*** &#039;&#039;&#039;Note&#039;&#039;&#039;: By default the distribution is going into the [https://gecko.readthedocs.io/en/latest/mobile/android/fennec/bouncer.html install bouncer APK]. To change that set &#039;&#039;MOZ_ANDROID_PACKAGE_INSTALL_BOUNCER&#039;&#039; to &#039;&#039;False&#039;&#039; in &#039;&#039;mobile/android/moz.configure&#039;&#039; (See {{bug|1258372}} for details) or add &#039;&#039;export MOZ_ANDROID_PACKAGE_INSTALL_BOUNCER=&#039;&#039; to mozconfig in Firefox 50 or later.&lt;br /&gt;
** For &#039;&#039;&#039;Firefox for Android 44 and earlier&#039;&#039;&#039;:&lt;br /&gt;
*** Put your distribution folder at &amp;lt;code&amp;gt;objdir/dist/bin/distribution&amp;lt;/code&amp;gt;&lt;br /&gt;
*** Run &amp;lt;code&amp;gt;./mach package&amp;lt;/code&amp;gt; to package the app&lt;br /&gt;
** When the app is launched, the distribution files will be copied out to &amp;lt;code&amp;gt;/data/data/org.mozilla.fennec_yourname/distribution&amp;lt;/code&amp;gt;, and they will override a ROM image distribution if it is present&lt;br /&gt;
&lt;br /&gt;
=== System distribution ===&lt;br /&gt;
* To create a ROM image distribution, follow these steps with a rooted phone:&lt;br /&gt;
** Copy the distribution files to a writable location&lt;br /&gt;
  adb shell mkdir /data/local/tmp/distribution&lt;br /&gt;
  adb push distribution /data/local/tmp/distribution&lt;br /&gt;
** Run &amp;lt;code&amp;gt;adb shell&amp;lt;/code&amp;gt; to get and adb shell&lt;br /&gt;
  $ su&lt;br /&gt;
  # mount&lt;br /&gt;
  # mount -o rw,remount /system&lt;br /&gt;
  # cp -r /data/local/tmp/distribution /system/&amp;lt;package&amp;gt;/  # (replace &amp;lt;package&amp;gt; with the ID for the package you want to test, e.g. org.mozilla.firefox or org.mozilla.fennec)&lt;br /&gt;
&lt;br /&gt;
==Testing distribution download==&lt;br /&gt;
A distribution download is triggered when two things are true:&lt;br /&gt;
&lt;br /&gt;
* This is the first run of Firefox (or Clear Data has been used).&lt;br /&gt;
* An &amp;lt;code&amp;gt;INSTALL_REFERRER&amp;lt;/code&amp;gt; intent has been received prior to launch.&lt;br /&gt;
&lt;br /&gt;
The Google Play app takes care of sending that intent. You can also manually send it via &amp;lt;code&amp;gt;adb shell&amp;lt;/code&amp;gt;. Assuming you&#039;re testing Nightly:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
am broadcast -a com.android.vending.INSTALL_REFERRER \&lt;br /&gt;
             -n org.mozilla.firefox/org.mozilla.gecko.distribution.ReferrerReceiver \&lt;br /&gt;
             -f 32 \&lt;br /&gt;
             --es &amp;quot;referrer&amp;quot; &amp;quot;utm_source=mozilla\&amp;amp;utm_content=testsigned\&amp;amp;utm_campaign=distribution&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will fetch the &amp;quot;testsigned.jar&amp;quot; distribution.&lt;br /&gt;
&lt;br /&gt;
(The -f 32 flag makes sure this intent is sent to stopped packages.)&lt;br /&gt;
&lt;br /&gt;
You can also do this from another Android application:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        Intent i = new Intent(&amp;quot;com.android.vending.INSTALL_REFERRER&amp;quot;);&lt;br /&gt;
        i.setPackage(&amp;quot;org.mozilla.firefox&amp;quot;);&lt;br /&gt;
        i.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);&lt;br /&gt;
        i.putExtra(&amp;quot;referrer&amp;quot;, &amp;quot;utm_source=mozilla&amp;amp;utm_content=testsigned&amp;amp;utm_campaign=distribution&amp;quot;);&lt;br /&gt;
        getContext().sendBroadcast(i);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Telemetry will be recorded for the download: &amp;lt;code&amp;gt;FENNEC_DISTRIBUTION_DOWNLOAD_TIME_MS&amp;lt;/code&amp;gt; records the download time in milliseconds, and &amp;lt;code&amp;gt;FENNEC_DISTRIBUTION_CODE_CATEGORY&amp;lt;/code&amp;gt; records the result. The value will be one of these:&lt;br /&gt;
&lt;br /&gt;
; 0: Unexpected HTTP status.&lt;br /&gt;
; 1: HTTP 1xx. Should not occur.&lt;br /&gt;
; 2: HTTP 2xx. The expected result.&lt;br /&gt;
; 3: HTTP 3xx. Should not occur.&lt;br /&gt;
; 4: HTTP 4xx. Should not occur.&lt;br /&gt;
; 5: HTTP 5xx. Should not occur.&lt;br /&gt;
; 6: The device was offline.&lt;br /&gt;
; 7: Generic fetch exception.&lt;br /&gt;
; 8: Failure during processing of downloaded zip.&lt;br /&gt;
; 9: Security exception: malformed, corrupted, or modified signatures.&lt;br /&gt;
; 10: Malformed distribution file.&lt;br /&gt;
; 11: Fetch: socket error.&lt;br /&gt;
; 12: Fetch: SSL error.&lt;br /&gt;
; 13: Fetch: non-success HTTP response.&lt;br /&gt;
; 14: Fetch: invalid Content-Type header received.&lt;br /&gt;
&lt;br /&gt;
==Crafting a distribution referrer==&lt;br /&gt;
&lt;br /&gt;
These are the fields exposed in a referrer URL to Play:&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;code&amp;gt;utm_content&amp;lt;/code&amp;gt;: &#039;&#039;&#039;The distribution name&#039;&#039;&#039;. Must be unique. Identifies the distribution name.&lt;br /&gt;
; &amp;lt;code&amp;gt;utm_campaign&amp;lt;/code&amp;gt;: &#039;&#039;&#039;The campaign name&#039;&#039;&#039;. Must be &amp;lt;code&amp;gt;distribution&amp;lt;/code&amp;gt;.&lt;br /&gt;
; &amp;lt;code&amp;gt;utm_source&amp;lt;/code&amp;gt;: Original referrer. Must be &amp;lt;code&amp;gt;mozilla&amp;lt;/code&amp;gt; for both downloadable distributions and campaign tracking.&lt;br /&gt;
; &amp;lt;code&amp;gt;utm_medium&amp;lt;/code&amp;gt;: Campaign medium. E.g., &amp;lt;code&amp;gt;email&amp;lt;/code&amp;gt;. Not used by Firefox.&lt;br /&gt;
; &amp;lt;code&amp;gt;utm_term&amp;lt;/code&amp;gt;: Search terms. E.g., &amp;lt;code&amp;gt;web+browser&amp;lt;/code&amp;gt;. Not used by Firefox.&lt;br /&gt;
&lt;br /&gt;
== Distribution bundles ==&lt;br /&gt;
&lt;br /&gt;
Firefox for Android 46.0 introduced support for distribution bundles based on the &#039;&#039;&#039;MCC&#039;&#039;&#039; (mobile country code, [https://en.wikipedia.org/wiki/Mobile_country_code]) and &#039;&#039;&#039;MNC&#039;&#039;&#039; (mobile network code) codes of the inserted SIM card. Instead of the default distribution directory Firefox will search a distribution in the following sub directories first:&lt;br /&gt;
* (distribution directory)/&#039;&#039;&amp;lt;MCC&amp;gt;&#039;&#039;/&#039;&#039;&amp;lt;MNC&amp;gt;&#039;&#039; - For bundled distributions for specific network providers&lt;br /&gt;
* (distribution directory)/&#039;&#039;&amp;lt;MCC&amp;gt;&#039;&#039; - For bundled distributions for specific countries&lt;br /&gt;
* (distribution directory)/&#039;&#039;default&#039;&#039; - For bundled distributions with no matching MCC/MNC&lt;br /&gt;
&lt;br /&gt;
=== Example distribution bundle ===&lt;br /&gt;
  distribution&lt;br /&gt;
  ├── 208                           // 208 = Country code of France&lt;br /&gt;
  │   └── bookmarks.json            // Bookmarks just for users with a SIM card of a French operator&lt;br /&gt;
  ├── 262                           // 262 = Country code of Germany&lt;br /&gt;
  │   └── 01                        // 01 = Network code of &amp;quot;Deutsche Telekom&amp;quot;&lt;br /&gt;
  │       ├── bookmarks.json        // Bookmarks..&lt;br /&gt;
  │       └── preferences.json      // ... and preferences just for users of a SIM card of &amp;quot;Deutsche Telekom&amp;quot;&lt;br /&gt;
  └── default                       // Default folder&lt;br /&gt;
      └── preferences.json          // Preferences for all users with different SIM cards.&lt;br /&gt;
&lt;br /&gt;
== Partner Content Providers ==&lt;br /&gt;
&lt;br /&gt;
Android system images can ship with two content providers to customize installed browsers:&lt;br /&gt;
* content://com.android.partnerbookmarks - For partner bookmarks&lt;br /&gt;
* content://com.android.partnerbrowsercustomizations - For customizations (Details see below)&lt;br /&gt;
&lt;br /&gt;
Firefox for Android supports reading data from both of those content providers (Starting with Firefox for Android 50.0) if this has been enabled by a distribution. If the following preferences are not written by a distribution then Firefox for Android will ignore the data from the partner content providers.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;/distribution/preferences.json:&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[..]&lt;br /&gt;
  &amp;quot;AndroidPreferences&amp;quot;: {&lt;br /&gt;
    &amp;quot;distribution.read_partner_bookmarks_provider&amp;quot;: true,&lt;br /&gt;
    &amp;quot;distribution.read_partner_customizations_provider&amp;quot;: true&lt;br /&gt;
  }&lt;br /&gt;
[..]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bookmarks Content Provider ===&lt;br /&gt;
&lt;br /&gt;
Firefox for Android (&amp;gt;= 50.0) supports reading bookmarks and folders from the content provider. Reading icons from the content provider is currently not supported (See {{bug|1286203}}). Editing and deleting bookmarks/folders is not supported yet but planned.&lt;br /&gt;
&lt;br /&gt;
An example implementation of the content provider can be found in the official Android source tree:&lt;br /&gt;
* https://android.googlesource.com/platform/packages/providers/PartnerBookmarksProvider/+/master/src/com/android/providers/partnerbookmarks/PartnerBookmarksProvider.java&lt;br /&gt;
&lt;br /&gt;
=== Customizations Content Provider ===&lt;br /&gt;
&lt;br /&gt;
Firefox for Android (&amp;gt;= 50.0) only supports reading the &#039;homepage&#039; from the content provider. All other values are ignored.&lt;br /&gt;
&lt;br /&gt;
content://com.android.partnerbrowsercustomizations&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Path !! Column !! Supported&lt;br /&gt;
|-&lt;br /&gt;
| /homepage || homepage || Yes&lt;br /&gt;
|-&lt;br /&gt;
| /disableincognitomode || disableincognitomode || No&lt;br /&gt;
|-&lt;br /&gt;
| /disablebookmarksediting || disablebookmarksediting || No&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Testing ===&lt;br /&gt;
&lt;br /&gt;
There&#039;s a test app with sample data available on GitHub:&lt;br /&gt;
* https://github.com/pocmo/BrowserPartner&lt;br /&gt;
&lt;br /&gt;
The test app uses slightly different content provider authorities to allow being installed on devices that already ship with partner content providers:&lt;br /&gt;
&lt;br /&gt;
* com.android.partnerbookmarks.&#039;&#039;&#039;&#039;&#039;test&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
* com.android.partnerbrowsercustomizations.&#039;&#039;&#039;&#039;&#039;test&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A custom Firefox build is required to read from the test content providers.&lt;/div&gt;</summary>
		<author><name>Nevin</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Mobile/Distribution_Files&amp;diff=1166481</id>
		<title>Mobile/Distribution Files</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Mobile/Distribution_Files&amp;diff=1166481"/>
		<updated>2017-03-23T14:21:37Z</updated>

		<summary type="html">&lt;p&gt;Nevin: Bug 1295675 - Allow for the setting of application level preferences from a distribution&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Like [https://wiki.mozilla.org/Distribution_INI_File desktop], mobile Firefox supplies a way for partners to repackage a set of customization files into a Firefox build without recompiling. We don&#039;t want to make custom binary builds that need to be QA&#039;d extensively. The &amp;quot;distribution files&amp;quot; concept allows a small set of external files to be used to customize a standard Firefox build. Things that can be customized include:&lt;br /&gt;
* Default bookmarks&lt;br /&gt;
* Preferences&lt;br /&gt;
* Lightweight themes&lt;br /&gt;
* Search engines&lt;br /&gt;
* Add-ons&lt;br /&gt;
* Quickshare defaults&lt;br /&gt;
* Suggested sites&lt;br /&gt;
&lt;br /&gt;
A sample distribution directory is available on [https://github.com/mozilla/fennec-distribution-sample github].&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
There are currently three ways distribution files can be ... distributed:&lt;br /&gt;
# &#039;&#039;&#039;&amp;lt;big&amp;gt;APK distributions&amp;lt;/big&amp;gt;&#039;&#039;&#039;: A folder of distribution files is repackaged into the Android APK. During the first run, those files are extracted from the APK and stored in the &amp;lt;code&amp;gt;/data/data/org.mozilla.firefox/distribution/*&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
# &#039;&#039;&#039;&amp;lt;big&amp;gt;System distributions&amp;lt;/big&amp;gt;&#039;&#039;&#039;: A folder of distribution files are shipped with the ROM image in &amp;lt;code&amp;gt;/system/org.mozilla.firefox/distribution/*&amp;lt;/code&amp;gt; directory. Shipping in this way ensures the files are not easily overwritten or removed by an application update. Note, files found in the &amp;lt;code&amp;gt;/data/data/org.mozilla.firefox/distribution/*&amp;lt;/code&amp;gt; directory will &amp;quot;win&amp;quot; in cases where both locations are used.&lt;br /&gt;
# &#039;&#039;&#039;&amp;lt;big&amp;gt;Over-the-air distributions&amp;lt;/big&amp;gt;&#039;&#039;&#039;: A distribution zip file is downloaded over-the-air as a result of a post-install referrer intent. See {{bug|1013024}}. This feature should ship with Firefox 33.&lt;br /&gt;
&lt;br /&gt;
Distributions are processed asynchronously during first run. Frontend code can chain post-distribution tasks via &amp;lt;code&amp;gt;Distribution.addOnDistributionReadyCallback&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Each type of data has its own nuances:&lt;br /&gt;
* Default bookmarks are read from the APK directly or from the &amp;quot;distribution&amp;quot; folder (if it already exists) any time a profile is created. These bookmarks are created prior to Firefox&#039;s default bookmarks.&lt;br /&gt;
* Preferences are set as &amp;quot;default&amp;quot; preferences on each run, since a &amp;quot;default&amp;quot; preference only lasts for the lifetime of the session. They are created as &amp;quot;default&amp;quot; preferences to allow &amp;quot;user&amp;quot; preferences to override them.&lt;br /&gt;
* Lightweight themes are actually just preferences. The data for the theme must live online somewhere. Typical places are the AMO theme or getpersonas.com sites.&lt;br /&gt;
* Search engine plugins and add-ons must follow a fixed folder layout.&lt;br /&gt;
* If distribution data is processed after the initial quickshare set is loaded, these options won&#039;t take effect until next run ({{bug|1021176}}).&lt;br /&gt;
&lt;br /&gt;
==Bookmarks==&lt;br /&gt;
Default bookmarks are specified in &#039;&#039;&#039;/distribution/bookmarks.json&#039;&#039;&#039;. This file should contain an array of bookmark JSON objects with the following properties:&lt;br /&gt;
* &#039;&#039;&#039;title&#039;&#039;&#039;: (required) string for the bookmark title&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: (required) string for the bookmark URL&lt;br /&gt;
* title.&amp;lt;locale&amp;gt;: (optional) title string for the given locale&lt;br /&gt;
* url.&amp;lt;locale&amp;gt;: (optional) URL string for the given locale&lt;br /&gt;
* icon: (optional) data URI for the bookmark favicon&lt;br /&gt;
* pinned: (optional) boolean for whether or not to pin this bookmark to the about:home top sites&lt;br /&gt;
** NOTE: If a bookmark is pinned, it is not visible in the Bookmarks list. Pinning only affects Tops Sites.&lt;br /&gt;
&lt;br /&gt;
Here is an example bookmarks.json:&lt;br /&gt;
 [&lt;br /&gt;
   {&lt;br /&gt;
     &amp;quot;title&amp;quot;: &amp;quot;Queso&amp;quot;,&lt;br /&gt;
     &amp;quot;url&amp;quot;: &amp;quot;http://queso.com/&amp;quot;,&lt;br /&gt;
     &amp;quot;title.en_US&amp;quot;: &amp;quot;Cheese&amp;quot;,&lt;br /&gt;
     &amp;quot;url.en_US&amp;quot;: &amp;quot;http://cheese.com&amp;quot;,&lt;br /&gt;
     &amp;quot;icon&amp;quot;: &amp;quot;data:image/png;base64,...&amp;quot;&lt;br /&gt;
   }&lt;br /&gt;
 ]&lt;br /&gt;
&lt;br /&gt;
==Preferences==&lt;br /&gt;
Preferences are specified in &#039;&#039;&#039;/distribution/preferences.json&#039;&#039;&#039;. This file should contain a JSON object with the following properties:&lt;br /&gt;
* Global&lt;br /&gt;
** &#039;&#039;&#039;id&#039;&#039;&#039;: (required) a short string unique to this distribution&lt;br /&gt;
** &#039;&#039;&#039;version&#039;&#039;&#039;: (required) version of the distribution (not the version of Firefox)&lt;br /&gt;
** &#039;&#039;&#039;about&#039;&#039;&#039;: (required) a short descriptive (ui-visible) string for this distribution&lt;br /&gt;
** about.&amp;lt;locale&amp;gt;: (optional) descriptive string for the given locale&lt;br /&gt;
* Preferences (optional)&lt;br /&gt;
** This sets default Gecko preferences for the profile (i.e. prefs that would appear in about:config)&lt;br /&gt;
* LocalizablePreferences (optional)&lt;br /&gt;
* LocalizablePreferences.&amp;lt;locale&amp;gt; (optional)&lt;br /&gt;
* ApplicationPreferences (optional)&lt;br /&gt;
** This sets as the app-scoped SharedPreferences for the entire application. Since GeckoPreferenceFragment only accept application-scoped sharedPreferences, this object will let partner also have the ability to override them. &lt;br /&gt;
* AndroidPreferences (optional)&lt;br /&gt;
** This sets Android SharedPreferences for the profile&lt;br /&gt;
&lt;br /&gt;
Here is an example preferences.json:&lt;br /&gt;
 {&lt;br /&gt;
   &amp;quot;Global&amp;quot;: {&lt;br /&gt;
     &amp;quot;id&amp;quot;: &amp;quot;testpartner&amp;quot;,&lt;br /&gt;
     &amp;quot;version&amp;quot;: 1.0,&lt;br /&gt;
     &amp;quot;about&amp;quot;: &amp;quot;Afiliado de Prueba&amp;quot;,&lt;br /&gt;
     &amp;quot;about.en-US&amp;quot;: &amp;quot;Test Partner&amp;quot;&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;Preferences&amp;quot;: {&lt;br /&gt;
     &amp;quot;distribution.test.string&amp;quot;: &amp;quot;a string pref&amp;quot;,&lt;br /&gt;
     &amp;quot;distribution.test.boolean&amp;quot;: true,&lt;br /&gt;
     &amp;quot;distribution.test.int&amp;quot;: 5&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;LocalizablePreferences&amp;quot;: {&lt;br /&gt;
     &amp;quot;distribution.test.localizeable&amp;quot;: &amp;quot;http://test.org/%LOCALE%/%LOCALE%/&amp;quot;,&lt;br /&gt;
     &amp;quot;distribution.test.localizeable-override&amp;quot;: &amp;quot;http://test.org/%LOCALE%/%LOCALE%/&amp;quot;&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;LocalizablePreferences.en-US&amp;quot;: {&lt;br /&gt;
     &amp;quot;distribution.test.localizeable-override&amp;quot;: &amp;quot;http://cheese.com&amp;quot;&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;AnpplicationPreferences&amp;quot;: {&lt;br /&gt;
     &amp;quot;homepage.for.new.tab.enabled&amp;quot;: &amp;quot;true&amp;quot;&lt;br /&gt;
   }&lt;br /&gt;
   &amp;quot;AndroidPreferences&amp;quot;: {&lt;br /&gt;
      &amp;quot;homepage&amp;quot;: &amp;quot;http://www.mozilla.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==Lightweight Themes==&lt;br /&gt;
Lightweight themes are specified in the &amp;quot;Preferences&amp;quot; section of /distribution/preferences.json. Here is an example of the lightweight theme preferences needed for this to work:&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;Preferences&amp;quot;: {&lt;br /&gt;
   &amp;quot;lightweightThemes.isThemeSelected&amp;quot;: true,&lt;br /&gt;
   &amp;quot;lightweightThemes.persisted.footerURL&amp;quot;: false,&lt;br /&gt;
   &amp;quot;lightweightThemes.persisted.headerURL&amp;quot;: false,&lt;br /&gt;
   &amp;quot;lightweightThemes.usedThemes&amp;quot;: &amp;quot;[{\&amp;quot;id\&amp;quot;:\&amp;quot;491717\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;colored trees\&amp;quot;,\&amp;quot;headerURL\&amp;quot;:\&amp;quot;http://getpersonas-cdn.mozilla.net/static/1/7/491717/trees.png?1358076678\&amp;quot;,\&amp;quot;footerURL\&amp;quot;:\&amp;quot;http://getpersonas-cdn.mozilla.net/static/1/7/491717/trees-base.png?1358076678\&amp;quot;,\&amp;quot;textcolor\&amp;quot;:\&amp;quot;#1d022b\&amp;quot;,\&amp;quot;accentcolor\&amp;quot;:\&amp;quot;#000000\&amp;quot;,\&amp;quot;iconURL\&amp;quot;:\&amp;quot;http://getpersonas-cdn.mozilla.net/static/1/7/491717/preview_small.jpg?1358076678\&amp;quot;,\&amp;quot;previewURL\&amp;quot;:\&amp;quot;http://getpersonas-cdn.mozilla.net/static/1/7/491717/preview.jpg?1358076678\&amp;quot;,\&amp;quot;author\&amp;quot;:\&amp;quot;birdyann\&amp;quot;,\&amp;quot;description\&amp;quot;:\&amp;quot;trees arbres colored colors couleurs\&amp;quot;,\&amp;quot;updateURL\&amp;quot;:\&amp;quot;https://www.getpersonas.com/en-US/update_check/491717\&amp;quot;,\&amp;quot;version\&amp;quot;:\&amp;quot;1358076678\&amp;quot;,\&amp;quot;updateDate\&amp;quot;:1359579038207,\&amp;quot;installDate\&amp;quot;:1359579038207}]&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==Search Plugins==&lt;br /&gt;
Include search plugins in a directory structure like the following, and they will be&lt;br /&gt;
automatically loaded:&lt;br /&gt;
&lt;br /&gt;
  * distribution/&lt;br /&gt;
    * searchplugins/&lt;br /&gt;
      * common/&lt;br /&gt;
        * &amp;lt;plugin.xml&amp;gt;&lt;br /&gt;
        * &amp;lt;plugin.xml&amp;gt;&lt;br /&gt;
        * ...&lt;br /&gt;
      * locale/&lt;br /&gt;
        * &amp;lt;locale&amp;gt;/&lt;br /&gt;
          * &amp;lt;plugin.xml&amp;gt;&lt;br /&gt;
          * &amp;lt;plugin.xml&amp;gt;&lt;br /&gt;
          * ...&lt;br /&gt;
        * &amp;lt;locale&amp;gt;/&lt;br /&gt;
          * &amp;lt;plugin.xml&amp;gt;&lt;br /&gt;
          * &amp;lt;plugin.xml&amp;gt;&lt;br /&gt;
          * ...&lt;br /&gt;
&lt;br /&gt;
If a directory for the locale the browser is running in doesn&#039;t exist, Firefox will automatically try the &#039;default&#039; locale, as defined by the &amp;lt;code&amp;gt;distribution.searchplugins.defaultLocale&amp;lt;/code&amp;gt; preference.&lt;br /&gt;
&lt;br /&gt;
To set a given search engine as the default, you need to use &amp;lt;code&amp;gt;LocalizablePreferences&amp;lt;/code&amp;gt; to override the &amp;lt;code&amp;gt;browser.search.defaultenginename&amp;lt;/code&amp;gt; preference. You should also override the &amp;lt;code&amp;gt;browser.search.order.1&amp;lt;/code&amp;gt; preference to put the default engine in the right sort order. For example:&lt;br /&gt;
&lt;br /&gt;
  {&lt;br /&gt;
    ...&lt;br /&gt;
    &amp;quot;LocalizablePreferences&amp;quot;: {&lt;br /&gt;
      &amp;quot;browser.search.defaultenginename&amp;quot;: &amp;quot;&amp;lt;name-of-engine&amp;gt;&amp;quot;,&lt;br /&gt;
      &amp;quot;browser.search.order.1&amp;quot;: &amp;quot;&amp;lt;name-of-engine&amp;gt;&amp;quot;&lt;br /&gt;
      ...&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
==Add-ons==&lt;br /&gt;
Include add-ons in an extensions directory as follows, and they will be&lt;br /&gt;
automatically loaded:&lt;br /&gt;
&lt;br /&gt;
  * distribution/&lt;br /&gt;
    * extensions/&lt;br /&gt;
      * someaddon@somedomain.com.xpi&lt;br /&gt;
      * ...&lt;br /&gt;
&lt;br /&gt;
Be sure to name the add-on XPI with the ID that&#039;s specified in the add-on&#039;s install.rdf.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; As of Firefox 41, we require all add-ons to be signed through AMO, so you should make sure this XPI is signed properly before shipping in a distribution.&lt;br /&gt;
&lt;br /&gt;
==Quickshare defaults==&lt;br /&gt;
Add a file named &amp;lt;code&amp;gt;history.xml&amp;lt;/code&amp;gt; under &amp;lt;code&amp;gt;distribution/quickshare&amp;lt;/code&amp;gt;. Its contents should be something like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;historical-records&amp;gt;&lt;br /&gt;
  &amp;lt;historical-record activity=&amp;quot;com.android.mms/com.android.mms.ui.ConversationComposer&amp;quot;&lt;br /&gt;
                     time=&amp;quot;0&amp;quot;&lt;br /&gt;
                     weight=&amp;quot;1&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/historical-records&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Suggested sites==&lt;br /&gt;
Added by {{bug|1012462}} in Firefox 33.&lt;br /&gt;
&lt;br /&gt;
Use a directory tree like the following. Locales are named via a locale code, such as &amp;lt;code&amp;gt;en-US&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
  * distribution/&lt;br /&gt;
    * suggestedsites/&lt;br /&gt;
      * locales/&lt;br /&gt;
        * &amp;lt;locale&amp;gt;/&lt;br /&gt;
          * suggestedsites.json&lt;br /&gt;
      * res/&lt;br /&gt;
        * hdpi/&lt;br /&gt;
          * &amp;lt;distro&amp;gt;.png&lt;br /&gt;
        * xxhdpi/&lt;br /&gt;
          * &amp;lt;distro&amp;gt;.png&lt;br /&gt;
&lt;br /&gt;
The suggestedsites.json file should be a JSON array:&lt;br /&gt;
&lt;br /&gt;
   [&lt;br /&gt;
     {&lt;br /&gt;
       url: &amp;quot;&amp;lt;site-url&amp;gt;&amp;quot;,&lt;br /&gt;
       title: &amp;quot;&amp;lt;site-title&amp;gt;&amp;quot;,&lt;br /&gt;
       imageurl: &amp;quot;gecko.distribution://&amp;lt;image-dir&amp;gt;/&amp;lt;image-name&amp;gt;&amp;quot;,&lt;br /&gt;
       bgcolor: &amp;quot;&amp;lt;color-hex-code&amp;gt;&amp;quot;, /* &amp;quot;#FF00FF&amp;quot; with leading &#039;#&#039; */&lt;br /&gt;
       trackingid: &amp;lt;tiles-id&amp;gt; /* optional integer */&lt;br /&gt;
     },&lt;br /&gt;
     ...&lt;br /&gt;
   ]&lt;br /&gt;
&lt;br /&gt;
Where &amp;lt;code&amp;gt;&amp;lt;image-dir&amp;gt;&amp;lt;/code&amp;gt; is the directory containing the density-specific image directories (&amp;lt;code&amp;gt;mdpi&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;hdpi&amp;lt;/code&amp;gt;, etc) and &amp;lt;code&amp;gt;&amp;lt;image-name&amp;gt;&amp;lt;/code&amp;gt; is the filename under the density-specific directories without the file extension. For example, &amp;lt;code&amp;gt;gecko.distribution://suggestedsites/res/distroimage&amp;lt;/code&amp;gt; image URL will be translated to &amp;lt;code&amp;gt;&amp;lt;distribution-root-dir&amp;gt;/suggestedsites/res/xhdpi/distroimage.png&amp;lt;/code&amp;gt; on a XHDPI device.&lt;br /&gt;
&lt;br /&gt;
The list of suggested sites from the distribution will be prepended to the default list of suggested sites that ships with Firefox.&lt;br /&gt;
&lt;br /&gt;
=== Image Specs ===&lt;br /&gt;
&lt;br /&gt;
When creating images for use in Suggested Sites, please use the following guidelines. Make sure you provide images for all the DPI levels or the thumbnail may not look good on some devices:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Images Sizes (Bounds)&#039;&#039;&#039;&lt;br /&gt;
* xxhdpi: 375x195&lt;br /&gt;
* xhdpi: 250x130&lt;br /&gt;
* hdpi: 188x98&lt;br /&gt;
* mdpi:125x65&lt;br /&gt;
&lt;br /&gt;
== Testing a distribution locally ==&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: you need a clean install. If you have already run Firefox, go to settings and clear the app&#039;s data&lt;br /&gt;
&lt;br /&gt;
=== APK distribution ===&lt;br /&gt;
* To create a repackaged distribution:&lt;br /&gt;
** For &#039;&#039;&#039;Firefox for Android 45 and later&#039;&#039;&#039;:&lt;br /&gt;
*** Your distribution folder contents should be at:&lt;br /&gt;
***:&amp;lt;pre&amp;gt;/path/to/fennec-distribution-sample/assets/distribution&amp;lt;/pre&amp;gt;&lt;br /&gt;
*** Add a line like the following to your mozconfig:&lt;br /&gt;
***:&amp;lt;pre&amp;gt;ac_add_options --with-android-distribution-directory=/path/to/fennec-distribution-sample&amp;lt;/pre&amp;gt;&lt;br /&gt;
*** Make sure you have run &amp;lt;code&amp;gt;./mach configure&amp;lt;/code&amp;gt; before building and packaging&lt;br /&gt;
*** See {{bug|1163082}} for details.&lt;br /&gt;
*** &#039;&#039;&#039;Note&#039;&#039;&#039;: By default the distribution is going into the [https://gecko.readthedocs.io/en/latest/mobile/android/fennec/bouncer.html install bouncer APK]. To change that set &#039;&#039;MOZ_ANDROID_PACKAGE_INSTALL_BOUNCER&#039;&#039; to &#039;&#039;False&#039;&#039; in &#039;&#039;mobile/android/moz.configure&#039;&#039; (See {{bug|1258372}} for details) or add &#039;&#039;export MOZ_ANDROID_PACKAGE_INSTALL_BOUNCER=&#039;&#039; to mozconfig in Firefox 50 or later.&lt;br /&gt;
** For &#039;&#039;&#039;Firefox for Android 44 and earlier&#039;&#039;&#039;:&lt;br /&gt;
*** Put your distribution folder at &amp;lt;code&amp;gt;objdir/dist/bin/distribution&amp;lt;/code&amp;gt;&lt;br /&gt;
*** Run &amp;lt;code&amp;gt;./mach package&amp;lt;/code&amp;gt; to package the app&lt;br /&gt;
** When the app is launched, the distribution files will be copied out to &amp;lt;code&amp;gt;/data/data/org.mozilla.fennec_yourname/distribution&amp;lt;/code&amp;gt;, and they will override a ROM image distribution if it is present&lt;br /&gt;
&lt;br /&gt;
=== System distribution ===&lt;br /&gt;
* To create a ROM image distribution, follow these steps with a rooted phone:&lt;br /&gt;
** Copy the distribution files to a writable location&lt;br /&gt;
  adb shell mkdir /data/local/tmp/distribution&lt;br /&gt;
  adb push distribution /data/local/tmp/distribution&lt;br /&gt;
** Run &amp;lt;code&amp;gt;adb shell&amp;lt;/code&amp;gt; to get and adb shell&lt;br /&gt;
  $ su&lt;br /&gt;
  # mount&lt;br /&gt;
  # mount -o rw,remount /system&lt;br /&gt;
  # cp -r /data/local/tmp/distribution /system/&amp;lt;package&amp;gt;/  # (replace &amp;lt;package&amp;gt; with the ID for the package you want to test, e.g. org.mozilla.firefox or org.mozilla.fennec)&lt;br /&gt;
&lt;br /&gt;
==Testing distribution download==&lt;br /&gt;
A distribution download is triggered when two things are true:&lt;br /&gt;
&lt;br /&gt;
* This is the first run of Firefox (or Clear Data has been used).&lt;br /&gt;
* An &amp;lt;code&amp;gt;INSTALL_REFERRER&amp;lt;/code&amp;gt; intent has been received prior to launch.&lt;br /&gt;
&lt;br /&gt;
The Google Play app takes care of sending that intent. You can also manually send it via &amp;lt;code&amp;gt;adb shell&amp;lt;/code&amp;gt;. Assuming you&#039;re testing Nightly:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
am broadcast -a com.android.vending.INSTALL_REFERRER \&lt;br /&gt;
             -n org.mozilla.firefox/org.mozilla.gecko.distribution.ReferrerReceiver \&lt;br /&gt;
             -f 32 \&lt;br /&gt;
             --es &amp;quot;referrer&amp;quot; &amp;quot;utm_source=mozilla\&amp;amp;utm_content=testsigned\&amp;amp;utm_campaign=distribution&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will fetch the &amp;quot;testsigned.jar&amp;quot; distribution.&lt;br /&gt;
&lt;br /&gt;
(The -f 32 flag makes sure this intent is sent to stopped packages.)&lt;br /&gt;
&lt;br /&gt;
You can also do this from another Android application:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        Intent i = new Intent(&amp;quot;com.android.vending.INSTALL_REFERRER&amp;quot;);&lt;br /&gt;
        i.setPackage(&amp;quot;org.mozilla.firefox&amp;quot;);&lt;br /&gt;
        i.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);&lt;br /&gt;
        i.putExtra(&amp;quot;referrer&amp;quot;, &amp;quot;utm_source=mozilla&amp;amp;utm_content=testsigned&amp;amp;utm_campaign=distribution&amp;quot;);&lt;br /&gt;
        getContext().sendBroadcast(i);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Telemetry will be recorded for the download: &amp;lt;code&amp;gt;FENNEC_DISTRIBUTION_DOWNLOAD_TIME_MS&amp;lt;/code&amp;gt; records the download time in milliseconds, and &amp;lt;code&amp;gt;FENNEC_DISTRIBUTION_CODE_CATEGORY&amp;lt;/code&amp;gt; records the result. The value will be one of these:&lt;br /&gt;
&lt;br /&gt;
; 0: Unexpected HTTP status.&lt;br /&gt;
; 1: HTTP 1xx. Should not occur.&lt;br /&gt;
; 2: HTTP 2xx. The expected result.&lt;br /&gt;
; 3: HTTP 3xx. Should not occur.&lt;br /&gt;
; 4: HTTP 4xx. Should not occur.&lt;br /&gt;
; 5: HTTP 5xx. Should not occur.&lt;br /&gt;
; 6: The device was offline.&lt;br /&gt;
; 7: Generic fetch exception.&lt;br /&gt;
; 8: Failure during processing of downloaded zip.&lt;br /&gt;
; 9: Security exception: malformed, corrupted, or modified signatures.&lt;br /&gt;
; 10: Malformed distribution file.&lt;br /&gt;
; 11: Fetch: socket error.&lt;br /&gt;
; 12: Fetch: SSL error.&lt;br /&gt;
; 13: Fetch: non-success HTTP response.&lt;br /&gt;
; 14: Fetch: invalid Content-Type header received.&lt;br /&gt;
&lt;br /&gt;
==Crafting a distribution referrer==&lt;br /&gt;
&lt;br /&gt;
These are the fields exposed in a referrer URL to Play:&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;code&amp;gt;utm_content&amp;lt;/code&amp;gt;: &#039;&#039;&#039;The distribution name&#039;&#039;&#039;. Must be unique. Identifies the distribution name.&lt;br /&gt;
; &amp;lt;code&amp;gt;utm_campaign&amp;lt;/code&amp;gt;: &#039;&#039;&#039;The campaign name&#039;&#039;&#039;. Must be &amp;lt;code&amp;gt;distribution&amp;lt;/code&amp;gt;.&lt;br /&gt;
; &amp;lt;code&amp;gt;utm_source&amp;lt;/code&amp;gt;: Original referrer. Must be &amp;lt;code&amp;gt;mozilla&amp;lt;/code&amp;gt; for both downloadable distributions and campaign tracking.&lt;br /&gt;
; &amp;lt;code&amp;gt;utm_medium&amp;lt;/code&amp;gt;: Campaign medium. E.g., &amp;lt;code&amp;gt;email&amp;lt;/code&amp;gt;. Not used by Firefox.&lt;br /&gt;
; &amp;lt;code&amp;gt;utm_term&amp;lt;/code&amp;gt;: Search terms. E.g., &amp;lt;code&amp;gt;web+browser&amp;lt;/code&amp;gt;. Not used by Firefox.&lt;br /&gt;
&lt;br /&gt;
== Distribution bundles ==&lt;br /&gt;
&lt;br /&gt;
Firefox for Android 46.0 introduced support for distribution bundles based on the &#039;&#039;&#039;MCC&#039;&#039;&#039; (mobile country code, [https://en.wikipedia.org/wiki/Mobile_country_code]) and &#039;&#039;&#039;MNC&#039;&#039;&#039; (mobile network code) codes of the inserted SIM card. Instead of the default distribution directory Firefox will search a distribution in the following sub directories first:&lt;br /&gt;
* (distribution directory)/&#039;&#039;&amp;lt;MCC&amp;gt;&#039;&#039;/&#039;&#039;&amp;lt;MNC&amp;gt;&#039;&#039; - For bundled distributions for specific network providers&lt;br /&gt;
* (distribution directory)/&#039;&#039;&amp;lt;MCC&amp;gt;&#039;&#039; - For bundled distributions for specific countries&lt;br /&gt;
* (distribution directory)/&#039;&#039;default&#039;&#039; - For bundled distributions with no matching MCC/MNC&lt;br /&gt;
&lt;br /&gt;
=== Example distribution bundle ===&lt;br /&gt;
  distribution&lt;br /&gt;
  ├── 208                           // 208 = Country code of France&lt;br /&gt;
  │   └── bookmarks.json            // Bookmarks just for users with a SIM card of a French operator&lt;br /&gt;
  ├── 262                           // 262 = Country code of Germany&lt;br /&gt;
  │   └── 01                        // 01 = Network code of &amp;quot;Deutsche Telekom&amp;quot;&lt;br /&gt;
  │       ├── bookmarks.json        // Bookmarks..&lt;br /&gt;
  │       └── preferences.json      // ... and preferences just for users of a SIM card of &amp;quot;Deutsche Telekom&amp;quot;&lt;br /&gt;
  └── default                       // Default folder&lt;br /&gt;
      └── preferences.json          // Preferences for all users with different SIM cards.&lt;br /&gt;
&lt;br /&gt;
== Partner Content Providers ==&lt;br /&gt;
&lt;br /&gt;
Android system images can ship with two content providers to customize installed browsers:&lt;br /&gt;
* content://com.android.partnerbookmarks - For partner bookmarks&lt;br /&gt;
* content://com.android.partnerbrowsercustomizations - For customizations (Details see below)&lt;br /&gt;
&lt;br /&gt;
Firefox for Android supports reading data from both of those content providers (Starting with Firefox for Android 50.0) if this has been enabled by a distribution. If the following preferences are not written by a distribution then Firefox for Android will ignore the data from the partner content providers.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;/distribution/preferences.json:&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[..]&lt;br /&gt;
  &amp;quot;AndroidPreferences&amp;quot;: {&lt;br /&gt;
    &amp;quot;distribution.read_partner_bookmarks_provider&amp;quot;: true,&lt;br /&gt;
    &amp;quot;distribution.read_partner_customizations_provider&amp;quot;: true&lt;br /&gt;
  }&lt;br /&gt;
[..]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bookmarks Content Provider ===&lt;br /&gt;
&lt;br /&gt;
Firefox for Android (&amp;gt;= 50.0) supports reading bookmarks and folders from the content provider. Reading icons from the content provider is currently not supported (See {{bug|1286203}}). Editing and deleting bookmarks/folders is not supported yet but planned.&lt;br /&gt;
&lt;br /&gt;
An example implementation of the content provider can be found in the official Android source tree:&lt;br /&gt;
* https://android.googlesource.com/platform/packages/providers/PartnerBookmarksProvider/+/master/src/com/android/providers/partnerbookmarks/PartnerBookmarksProvider.java&lt;br /&gt;
&lt;br /&gt;
=== Customizations Content Provider ===&lt;br /&gt;
&lt;br /&gt;
Firefox for Android (&amp;gt;= 50.0) only supports reading the &#039;homepage&#039; from the content provider. All other values are ignored.&lt;br /&gt;
&lt;br /&gt;
content://com.android.partnerbrowsercustomizations&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Path !! Column !! Supported&lt;br /&gt;
|-&lt;br /&gt;
| /homepage || homepage || Yes&lt;br /&gt;
|-&lt;br /&gt;
| /disableincognitomode || disableincognitomode || No&lt;br /&gt;
|-&lt;br /&gt;
| /disablebookmarksediting || disablebookmarksediting || No&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Testing ===&lt;br /&gt;
&lt;br /&gt;
There&#039;s a test app with sample data available on GitHub:&lt;br /&gt;
* https://github.com/pocmo/BrowserPartner&lt;br /&gt;
&lt;br /&gt;
The test app uses slightly different content provider authorities to allow being installed on devices that already ship with partner content providers:&lt;br /&gt;
&lt;br /&gt;
* com.android.partnerbookmarks.&#039;&#039;&#039;&#039;&#039;test&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
* com.android.partnerbrowsercustomizations.&#039;&#039;&#039;&#039;&#039;test&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A custom Firefox build is required to read from the test content providers.&lt;/div&gt;</summary>
		<author><name>Nevin</name></author>
	</entry>
	<entry>
		<id>https://wiki.mozilla.org/index.php?title=Mobile/Distribution_Files&amp;diff=1166480</id>
		<title>Mobile/Distribution Files</title>
		<link rel="alternate" type="text/html" href="https://wiki.mozilla.org/index.php?title=Mobile/Distribution_Files&amp;diff=1166480"/>
		<updated>2017-03-23T14:10:17Z</updated>

		<summary type="html">&lt;p&gt;Nevin: Bug 1295675 - Allow for the setting of application level preferences from a distribution&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Like [https://wiki.mozilla.org/Distribution_INI_File desktop], mobile Firefox supplies a way for partners to repackage a set of customization files into a Firefox build without recompiling. We don&#039;t want to make custom binary builds that need to be QA&#039;d extensively. The &amp;quot;distribution files&amp;quot; concept allows a small set of external files to be used to customize a standard Firefox build. Things that can be customized include:&lt;br /&gt;
* Default bookmarks&lt;br /&gt;
* Preferences&lt;br /&gt;
* Lightweight themes&lt;br /&gt;
* Search engines&lt;br /&gt;
* Add-ons&lt;br /&gt;
* Quickshare defaults&lt;br /&gt;
* Suggested sites&lt;br /&gt;
&lt;br /&gt;
A sample distribution directory is available on [https://github.com/mozilla/fennec-distribution-sample github].&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
There are currently three ways distribution files can be ... distributed:&lt;br /&gt;
# &#039;&#039;&#039;&amp;lt;big&amp;gt;APK distributions&amp;lt;/big&amp;gt;&#039;&#039;&#039;: A folder of distribution files is repackaged into the Android APK. During the first run, those files are extracted from the APK and stored in the &amp;lt;code&amp;gt;/data/data/org.mozilla.firefox/distribution/*&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
# &#039;&#039;&#039;&amp;lt;big&amp;gt;System distributions&amp;lt;/big&amp;gt;&#039;&#039;&#039;: A folder of distribution files are shipped with the ROM image in &amp;lt;code&amp;gt;/system/org.mozilla.firefox/distribution/*&amp;lt;/code&amp;gt; directory. Shipping in this way ensures the files are not easily overwritten or removed by an application update. Note, files found in the &amp;lt;code&amp;gt;/data/data/org.mozilla.firefox/distribution/*&amp;lt;/code&amp;gt; directory will &amp;quot;win&amp;quot; in cases where both locations are used.&lt;br /&gt;
# &#039;&#039;&#039;&amp;lt;big&amp;gt;Over-the-air distributions&amp;lt;/big&amp;gt;&#039;&#039;&#039;: A distribution zip file is downloaded over-the-air as a result of a post-install referrer intent. See {{bug|1013024}}. This feature should ship with Firefox 33.&lt;br /&gt;
&lt;br /&gt;
Distributions are processed asynchronously during first run. Frontend code can chain post-distribution tasks via &amp;lt;code&amp;gt;Distribution.addOnDistributionReadyCallback&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Each type of data has its own nuances:&lt;br /&gt;
* Default bookmarks are read from the APK directly or from the &amp;quot;distribution&amp;quot; folder (if it already exists) any time a profile is created. These bookmarks are created prior to Firefox&#039;s default bookmarks.&lt;br /&gt;
* Preferences are set as &amp;quot;default&amp;quot; preferences on each run, since a &amp;quot;default&amp;quot; preference only lasts for the lifetime of the session. They are created as &amp;quot;default&amp;quot; preferences to allow &amp;quot;user&amp;quot; preferences to override them.&lt;br /&gt;
* Lightweight themes are actually just preferences. The data for the theme must live online somewhere. Typical places are the AMO theme or getpersonas.com sites.&lt;br /&gt;
* Search engine plugins and add-ons must follow a fixed folder layout.&lt;br /&gt;
* If distribution data is processed after the initial quickshare set is loaded, these options won&#039;t take effect until next run ({{bug|1021176}}).&lt;br /&gt;
&lt;br /&gt;
==Bookmarks==&lt;br /&gt;
Default bookmarks are specified in &#039;&#039;&#039;/distribution/bookmarks.json&#039;&#039;&#039;. This file should contain an array of bookmark JSON objects with the following properties:&lt;br /&gt;
* &#039;&#039;&#039;title&#039;&#039;&#039;: (required) string for the bookmark title&lt;br /&gt;
* &#039;&#039;&#039;url&#039;&#039;&#039;: (required) string for the bookmark URL&lt;br /&gt;
* title.&amp;lt;locale&amp;gt;: (optional) title string for the given locale&lt;br /&gt;
* url.&amp;lt;locale&amp;gt;: (optional) URL string for the given locale&lt;br /&gt;
* icon: (optional) data URI for the bookmark favicon&lt;br /&gt;
* pinned: (optional) boolean for whether or not to pin this bookmark to the about:home top sites&lt;br /&gt;
** NOTE: If a bookmark is pinned, it is not visible in the Bookmarks list. Pinning only affects Tops Sites.&lt;br /&gt;
&lt;br /&gt;
Here is an example bookmarks.json:&lt;br /&gt;
 [&lt;br /&gt;
   {&lt;br /&gt;
     &amp;quot;title&amp;quot;: &amp;quot;Queso&amp;quot;,&lt;br /&gt;
     &amp;quot;url&amp;quot;: &amp;quot;http://queso.com/&amp;quot;,&lt;br /&gt;
     &amp;quot;title.en_US&amp;quot;: &amp;quot;Cheese&amp;quot;,&lt;br /&gt;
     &amp;quot;url.en_US&amp;quot;: &amp;quot;http://cheese.com&amp;quot;,&lt;br /&gt;
     &amp;quot;icon&amp;quot;: &amp;quot;data:image/png;base64,...&amp;quot;&lt;br /&gt;
   }&lt;br /&gt;
 ]&lt;br /&gt;
&lt;br /&gt;
==Preferences==&lt;br /&gt;
Preferences are specified in &#039;&#039;&#039;/distribution/preferences.json&#039;&#039;&#039;. This file should contain a JSON object with the following properties:&lt;br /&gt;
* Global&lt;br /&gt;
** &#039;&#039;&#039;id&#039;&#039;&#039;: (required) a short string unique to this distribution&lt;br /&gt;
** &#039;&#039;&#039;version&#039;&#039;&#039;: (required) version of the distribution (not the version of Firefox)&lt;br /&gt;
** &#039;&#039;&#039;about&#039;&#039;&#039;: (required) a short descriptive (ui-visible) string for this distribution&lt;br /&gt;
** about.&amp;lt;locale&amp;gt;: (optional) descriptive string for the given locale&lt;br /&gt;
* Preferences (optional)&lt;br /&gt;
** This sets default Gecko preferences for the profile (i.e. prefs that would appear in about:config)&lt;br /&gt;
* LocalizablePreferences (optional)&lt;br /&gt;
* LocalizablePreferences.&amp;lt;locale&amp;gt; (optional)&lt;br /&gt;
* ApplicationPreferences (optional)&lt;br /&gt;
* AndroidPreferences (optional)&lt;br /&gt;
** This sets Android SharedPreferences for the profile&lt;br /&gt;
&lt;br /&gt;
Here is an example preferences.json:&lt;br /&gt;
 {&lt;br /&gt;
   &amp;quot;Global&amp;quot;: {&lt;br /&gt;
     &amp;quot;id&amp;quot;: &amp;quot;testpartner&amp;quot;,&lt;br /&gt;
     &amp;quot;version&amp;quot;: 1.0,&lt;br /&gt;
     &amp;quot;about&amp;quot;: &amp;quot;Afiliado de Prueba&amp;quot;,&lt;br /&gt;
     &amp;quot;about.en-US&amp;quot;: &amp;quot;Test Partner&amp;quot;&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;Preferences&amp;quot;: {&lt;br /&gt;
     &amp;quot;distribution.test.string&amp;quot;: &amp;quot;a string pref&amp;quot;,&lt;br /&gt;
     &amp;quot;distribution.test.boolean&amp;quot;: true,&lt;br /&gt;
     &amp;quot;distribution.test.int&amp;quot;: 5&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;LocalizablePreferences&amp;quot;: {&lt;br /&gt;
     &amp;quot;distribution.test.localizeable&amp;quot;: &amp;quot;http://test.org/%LOCALE%/%LOCALE%/&amp;quot;,&lt;br /&gt;
     &amp;quot;distribution.test.localizeable-override&amp;quot;: &amp;quot;http://test.org/%LOCALE%/%LOCALE%/&amp;quot;&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;LocalizablePreferences.en-US&amp;quot;: {&lt;br /&gt;
     &amp;quot;distribution.test.localizeable-override&amp;quot;: &amp;quot;http://cheese.com&amp;quot;&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;AnpplicationPreferences&amp;quot;: {&lt;br /&gt;
     &amp;quot;homepage.for.new.tab.enabled&amp;quot;: &amp;quot;true&amp;quot;&lt;br /&gt;
   }&lt;br /&gt;
   &amp;quot;AndroidPreferences&amp;quot;: {&lt;br /&gt;
      &amp;quot;homepage&amp;quot;: &amp;quot;http://www.mozilla.com&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==Lightweight Themes==&lt;br /&gt;
Lightweight themes are specified in the &amp;quot;Preferences&amp;quot; section of /distribution/preferences.json. Here is an example of the lightweight theme preferences needed for this to work:&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;Preferences&amp;quot;: {&lt;br /&gt;
   &amp;quot;lightweightThemes.isThemeSelected&amp;quot;: true,&lt;br /&gt;
   &amp;quot;lightweightThemes.persisted.footerURL&amp;quot;: false,&lt;br /&gt;
   &amp;quot;lightweightThemes.persisted.headerURL&amp;quot;: false,&lt;br /&gt;
   &amp;quot;lightweightThemes.usedThemes&amp;quot;: &amp;quot;[{\&amp;quot;id\&amp;quot;:\&amp;quot;491717\&amp;quot;,\&amp;quot;name\&amp;quot;:\&amp;quot;colored trees\&amp;quot;,\&amp;quot;headerURL\&amp;quot;:\&amp;quot;http://getpersonas-cdn.mozilla.net/static/1/7/491717/trees.png?1358076678\&amp;quot;,\&amp;quot;footerURL\&amp;quot;:\&amp;quot;http://getpersonas-cdn.mozilla.net/static/1/7/491717/trees-base.png?1358076678\&amp;quot;,\&amp;quot;textcolor\&amp;quot;:\&amp;quot;#1d022b\&amp;quot;,\&amp;quot;accentcolor\&amp;quot;:\&amp;quot;#000000\&amp;quot;,\&amp;quot;iconURL\&amp;quot;:\&amp;quot;http://getpersonas-cdn.mozilla.net/static/1/7/491717/preview_small.jpg?1358076678\&amp;quot;,\&amp;quot;previewURL\&amp;quot;:\&amp;quot;http://getpersonas-cdn.mozilla.net/static/1/7/491717/preview.jpg?1358076678\&amp;quot;,\&amp;quot;author\&amp;quot;:\&amp;quot;birdyann\&amp;quot;,\&amp;quot;description\&amp;quot;:\&amp;quot;trees arbres colored colors couleurs\&amp;quot;,\&amp;quot;updateURL\&amp;quot;:\&amp;quot;https://www.getpersonas.com/en-US/update_check/491717\&amp;quot;,\&amp;quot;version\&amp;quot;:\&amp;quot;1358076678\&amp;quot;,\&amp;quot;updateDate\&amp;quot;:1359579038207,\&amp;quot;installDate\&amp;quot;:1359579038207}]&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
==Search Plugins==&lt;br /&gt;
Include search plugins in a directory structure like the following, and they will be&lt;br /&gt;
automatically loaded:&lt;br /&gt;
&lt;br /&gt;
  * distribution/&lt;br /&gt;
    * searchplugins/&lt;br /&gt;
      * common/&lt;br /&gt;
        * &amp;lt;plugin.xml&amp;gt;&lt;br /&gt;
        * &amp;lt;plugin.xml&amp;gt;&lt;br /&gt;
        * ...&lt;br /&gt;
      * locale/&lt;br /&gt;
        * &amp;lt;locale&amp;gt;/&lt;br /&gt;
          * &amp;lt;plugin.xml&amp;gt;&lt;br /&gt;
          * &amp;lt;plugin.xml&amp;gt;&lt;br /&gt;
          * ...&lt;br /&gt;
        * &amp;lt;locale&amp;gt;/&lt;br /&gt;
          * &amp;lt;plugin.xml&amp;gt;&lt;br /&gt;
          * &amp;lt;plugin.xml&amp;gt;&lt;br /&gt;
          * ...&lt;br /&gt;
&lt;br /&gt;
If a directory for the locale the browser is running in doesn&#039;t exist, Firefox will automatically try the &#039;default&#039; locale, as defined by the &amp;lt;code&amp;gt;distribution.searchplugins.defaultLocale&amp;lt;/code&amp;gt; preference.&lt;br /&gt;
&lt;br /&gt;
To set a given search engine as the default, you need to use &amp;lt;code&amp;gt;LocalizablePreferences&amp;lt;/code&amp;gt; to override the &amp;lt;code&amp;gt;browser.search.defaultenginename&amp;lt;/code&amp;gt; preference. You should also override the &amp;lt;code&amp;gt;browser.search.order.1&amp;lt;/code&amp;gt; preference to put the default engine in the right sort order. For example:&lt;br /&gt;
&lt;br /&gt;
  {&lt;br /&gt;
    ...&lt;br /&gt;
    &amp;quot;LocalizablePreferences&amp;quot;: {&lt;br /&gt;
      &amp;quot;browser.search.defaultenginename&amp;quot;: &amp;quot;&amp;lt;name-of-engine&amp;gt;&amp;quot;,&lt;br /&gt;
      &amp;quot;browser.search.order.1&amp;quot;: &amp;quot;&amp;lt;name-of-engine&amp;gt;&amp;quot;&lt;br /&gt;
      ...&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
==Add-ons==&lt;br /&gt;
Include add-ons in an extensions directory as follows, and they will be&lt;br /&gt;
automatically loaded:&lt;br /&gt;
&lt;br /&gt;
  * distribution/&lt;br /&gt;
    * extensions/&lt;br /&gt;
      * someaddon@somedomain.com.xpi&lt;br /&gt;
      * ...&lt;br /&gt;
&lt;br /&gt;
Be sure to name the add-on XPI with the ID that&#039;s specified in the add-on&#039;s install.rdf.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; As of Firefox 41, we require all add-ons to be signed through AMO, so you should make sure this XPI is signed properly before shipping in a distribution.&lt;br /&gt;
&lt;br /&gt;
==Quickshare defaults==&lt;br /&gt;
Add a file named &amp;lt;code&amp;gt;history.xml&amp;lt;/code&amp;gt; under &amp;lt;code&amp;gt;distribution/quickshare&amp;lt;/code&amp;gt;. Its contents should be something like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;historical-records&amp;gt;&lt;br /&gt;
  &amp;lt;historical-record activity=&amp;quot;com.android.mms/com.android.mms.ui.ConversationComposer&amp;quot;&lt;br /&gt;
                     time=&amp;quot;0&amp;quot;&lt;br /&gt;
                     weight=&amp;quot;1&amp;quot;/&amp;gt;&lt;br /&gt;
&amp;lt;/historical-records&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Suggested sites==&lt;br /&gt;
Added by {{bug|1012462}} in Firefox 33.&lt;br /&gt;
&lt;br /&gt;
Use a directory tree like the following. Locales are named via a locale code, such as &amp;lt;code&amp;gt;en-US&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
  * distribution/&lt;br /&gt;
    * suggestedsites/&lt;br /&gt;
      * locales/&lt;br /&gt;
        * &amp;lt;locale&amp;gt;/&lt;br /&gt;
          * suggestedsites.json&lt;br /&gt;
      * res/&lt;br /&gt;
        * hdpi/&lt;br /&gt;
          * &amp;lt;distro&amp;gt;.png&lt;br /&gt;
        * xxhdpi/&lt;br /&gt;
          * &amp;lt;distro&amp;gt;.png&lt;br /&gt;
&lt;br /&gt;
The suggestedsites.json file should be a JSON array:&lt;br /&gt;
&lt;br /&gt;
   [&lt;br /&gt;
     {&lt;br /&gt;
       url: &amp;quot;&amp;lt;site-url&amp;gt;&amp;quot;,&lt;br /&gt;
       title: &amp;quot;&amp;lt;site-title&amp;gt;&amp;quot;,&lt;br /&gt;
       imageurl: &amp;quot;gecko.distribution://&amp;lt;image-dir&amp;gt;/&amp;lt;image-name&amp;gt;&amp;quot;,&lt;br /&gt;
       bgcolor: &amp;quot;&amp;lt;color-hex-code&amp;gt;&amp;quot;, /* &amp;quot;#FF00FF&amp;quot; with leading &#039;#&#039; */&lt;br /&gt;
       trackingid: &amp;lt;tiles-id&amp;gt; /* optional integer */&lt;br /&gt;
     },&lt;br /&gt;
     ...&lt;br /&gt;
   ]&lt;br /&gt;
&lt;br /&gt;
Where &amp;lt;code&amp;gt;&amp;lt;image-dir&amp;gt;&amp;lt;/code&amp;gt; is the directory containing the density-specific image directories (&amp;lt;code&amp;gt;mdpi&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;hdpi&amp;lt;/code&amp;gt;, etc) and &amp;lt;code&amp;gt;&amp;lt;image-name&amp;gt;&amp;lt;/code&amp;gt; is the filename under the density-specific directories without the file extension. For example, &amp;lt;code&amp;gt;gecko.distribution://suggestedsites/res/distroimage&amp;lt;/code&amp;gt; image URL will be translated to &amp;lt;code&amp;gt;&amp;lt;distribution-root-dir&amp;gt;/suggestedsites/res/xhdpi/distroimage.png&amp;lt;/code&amp;gt; on a XHDPI device.&lt;br /&gt;
&lt;br /&gt;
The list of suggested sites from the distribution will be prepended to the default list of suggested sites that ships with Firefox.&lt;br /&gt;
&lt;br /&gt;
=== Image Specs ===&lt;br /&gt;
&lt;br /&gt;
When creating images for use in Suggested Sites, please use the following guidelines. Make sure you provide images for all the DPI levels or the thumbnail may not look good on some devices:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Images Sizes (Bounds)&#039;&#039;&#039;&lt;br /&gt;
* xxhdpi: 375x195&lt;br /&gt;
* xhdpi: 250x130&lt;br /&gt;
* hdpi: 188x98&lt;br /&gt;
* mdpi:125x65&lt;br /&gt;
&lt;br /&gt;
== Testing a distribution locally ==&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: you need a clean install. If you have already run Firefox, go to settings and clear the app&#039;s data&lt;br /&gt;
&lt;br /&gt;
=== APK distribution ===&lt;br /&gt;
* To create a repackaged distribution:&lt;br /&gt;
** For &#039;&#039;&#039;Firefox for Android 45 and later&#039;&#039;&#039;:&lt;br /&gt;
*** Your distribution folder contents should be at:&lt;br /&gt;
***:&amp;lt;pre&amp;gt;/path/to/fennec-distribution-sample/assets/distribution&amp;lt;/pre&amp;gt;&lt;br /&gt;
*** Add a line like the following to your mozconfig:&lt;br /&gt;
***:&amp;lt;pre&amp;gt;ac_add_options --with-android-distribution-directory=/path/to/fennec-distribution-sample&amp;lt;/pre&amp;gt;&lt;br /&gt;
*** Make sure you have run &amp;lt;code&amp;gt;./mach configure&amp;lt;/code&amp;gt; before building and packaging&lt;br /&gt;
*** See {{bug|1163082}} for details.&lt;br /&gt;
*** &#039;&#039;&#039;Note&#039;&#039;&#039;: By default the distribution is going into the [https://gecko.readthedocs.io/en/latest/mobile/android/fennec/bouncer.html install bouncer APK]. To change that set &#039;&#039;MOZ_ANDROID_PACKAGE_INSTALL_BOUNCER&#039;&#039; to &#039;&#039;False&#039;&#039; in &#039;&#039;mobile/android/moz.configure&#039;&#039; (See {{bug|1258372}} for details) or add &#039;&#039;export MOZ_ANDROID_PACKAGE_INSTALL_BOUNCER=&#039;&#039; to mozconfig in Firefox 50 or later.&lt;br /&gt;
** For &#039;&#039;&#039;Firefox for Android 44 and earlier&#039;&#039;&#039;:&lt;br /&gt;
*** Put your distribution folder at &amp;lt;code&amp;gt;objdir/dist/bin/distribution&amp;lt;/code&amp;gt;&lt;br /&gt;
*** Run &amp;lt;code&amp;gt;./mach package&amp;lt;/code&amp;gt; to package the app&lt;br /&gt;
** When the app is launched, the distribution files will be copied out to &amp;lt;code&amp;gt;/data/data/org.mozilla.fennec_yourname/distribution&amp;lt;/code&amp;gt;, and they will override a ROM image distribution if it is present&lt;br /&gt;
&lt;br /&gt;
=== System distribution ===&lt;br /&gt;
* To create a ROM image distribution, follow these steps with a rooted phone:&lt;br /&gt;
** Copy the distribution files to a writable location&lt;br /&gt;
  adb shell mkdir /data/local/tmp/distribution&lt;br /&gt;
  adb push distribution /data/local/tmp/distribution&lt;br /&gt;
** Run &amp;lt;code&amp;gt;adb shell&amp;lt;/code&amp;gt; to get and adb shell&lt;br /&gt;
  $ su&lt;br /&gt;
  # mount&lt;br /&gt;
  # mount -o rw,remount /system&lt;br /&gt;
  # cp -r /data/local/tmp/distribution /system/&amp;lt;package&amp;gt;/  # (replace &amp;lt;package&amp;gt; with the ID for the package you want to test, e.g. org.mozilla.firefox or org.mozilla.fennec)&lt;br /&gt;
&lt;br /&gt;
==Testing distribution download==&lt;br /&gt;
A distribution download is triggered when two things are true:&lt;br /&gt;
&lt;br /&gt;
* This is the first run of Firefox (or Clear Data has been used).&lt;br /&gt;
* An &amp;lt;code&amp;gt;INSTALL_REFERRER&amp;lt;/code&amp;gt; intent has been received prior to launch.&lt;br /&gt;
&lt;br /&gt;
The Google Play app takes care of sending that intent. You can also manually send it via &amp;lt;code&amp;gt;adb shell&amp;lt;/code&amp;gt;. Assuming you&#039;re testing Nightly:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
am broadcast -a com.android.vending.INSTALL_REFERRER \&lt;br /&gt;
             -n org.mozilla.firefox/org.mozilla.gecko.distribution.ReferrerReceiver \&lt;br /&gt;
             -f 32 \&lt;br /&gt;
             --es &amp;quot;referrer&amp;quot; &amp;quot;utm_source=mozilla\&amp;amp;utm_content=testsigned\&amp;amp;utm_campaign=distribution&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will fetch the &amp;quot;testsigned.jar&amp;quot; distribution.&lt;br /&gt;
&lt;br /&gt;
(The -f 32 flag makes sure this intent is sent to stopped packages.)&lt;br /&gt;
&lt;br /&gt;
You can also do this from another Android application:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        Intent i = new Intent(&amp;quot;com.android.vending.INSTALL_REFERRER&amp;quot;);&lt;br /&gt;
        i.setPackage(&amp;quot;org.mozilla.firefox&amp;quot;);&lt;br /&gt;
        i.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);&lt;br /&gt;
        i.putExtra(&amp;quot;referrer&amp;quot;, &amp;quot;utm_source=mozilla&amp;amp;utm_content=testsigned&amp;amp;utm_campaign=distribution&amp;quot;);&lt;br /&gt;
        getContext().sendBroadcast(i);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Telemetry will be recorded for the download: &amp;lt;code&amp;gt;FENNEC_DISTRIBUTION_DOWNLOAD_TIME_MS&amp;lt;/code&amp;gt; records the download time in milliseconds, and &amp;lt;code&amp;gt;FENNEC_DISTRIBUTION_CODE_CATEGORY&amp;lt;/code&amp;gt; records the result. The value will be one of these:&lt;br /&gt;
&lt;br /&gt;
; 0: Unexpected HTTP status.&lt;br /&gt;
; 1: HTTP 1xx. Should not occur.&lt;br /&gt;
; 2: HTTP 2xx. The expected result.&lt;br /&gt;
; 3: HTTP 3xx. Should not occur.&lt;br /&gt;
; 4: HTTP 4xx. Should not occur.&lt;br /&gt;
; 5: HTTP 5xx. Should not occur.&lt;br /&gt;
; 6: The device was offline.&lt;br /&gt;
; 7: Generic fetch exception.&lt;br /&gt;
; 8: Failure during processing of downloaded zip.&lt;br /&gt;
; 9: Security exception: malformed, corrupted, or modified signatures.&lt;br /&gt;
; 10: Malformed distribution file.&lt;br /&gt;
; 11: Fetch: socket error.&lt;br /&gt;
; 12: Fetch: SSL error.&lt;br /&gt;
; 13: Fetch: non-success HTTP response.&lt;br /&gt;
; 14: Fetch: invalid Content-Type header received.&lt;br /&gt;
&lt;br /&gt;
==Crafting a distribution referrer==&lt;br /&gt;
&lt;br /&gt;
These are the fields exposed in a referrer URL to Play:&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;code&amp;gt;utm_content&amp;lt;/code&amp;gt;: &#039;&#039;&#039;The distribution name&#039;&#039;&#039;. Must be unique. Identifies the distribution name.&lt;br /&gt;
; &amp;lt;code&amp;gt;utm_campaign&amp;lt;/code&amp;gt;: &#039;&#039;&#039;The campaign name&#039;&#039;&#039;. Must be &amp;lt;code&amp;gt;distribution&amp;lt;/code&amp;gt;.&lt;br /&gt;
; &amp;lt;code&amp;gt;utm_source&amp;lt;/code&amp;gt;: Original referrer. Must be &amp;lt;code&amp;gt;mozilla&amp;lt;/code&amp;gt; for both downloadable distributions and campaign tracking.&lt;br /&gt;
; &amp;lt;code&amp;gt;utm_medium&amp;lt;/code&amp;gt;: Campaign medium. E.g., &amp;lt;code&amp;gt;email&amp;lt;/code&amp;gt;. Not used by Firefox.&lt;br /&gt;
; &amp;lt;code&amp;gt;utm_term&amp;lt;/code&amp;gt;: Search terms. E.g., &amp;lt;code&amp;gt;web+browser&amp;lt;/code&amp;gt;. Not used by Firefox.&lt;br /&gt;
&lt;br /&gt;
== Distribution bundles ==&lt;br /&gt;
&lt;br /&gt;
Firefox for Android 46.0 introduced support for distribution bundles based on the &#039;&#039;&#039;MCC&#039;&#039;&#039; (mobile country code, [https://en.wikipedia.org/wiki/Mobile_country_code]) and &#039;&#039;&#039;MNC&#039;&#039;&#039; (mobile network code) codes of the inserted SIM card. Instead of the default distribution directory Firefox will search a distribution in the following sub directories first:&lt;br /&gt;
* (distribution directory)/&#039;&#039;&amp;lt;MCC&amp;gt;&#039;&#039;/&#039;&#039;&amp;lt;MNC&amp;gt;&#039;&#039; - For bundled distributions for specific network providers&lt;br /&gt;
* (distribution directory)/&#039;&#039;&amp;lt;MCC&amp;gt;&#039;&#039; - For bundled distributions for specific countries&lt;br /&gt;
* (distribution directory)/&#039;&#039;default&#039;&#039; - For bundled distributions with no matching MCC/MNC&lt;br /&gt;
&lt;br /&gt;
=== Example distribution bundle ===&lt;br /&gt;
  distribution&lt;br /&gt;
  ├── 208                           // 208 = Country code of France&lt;br /&gt;
  │   └── bookmarks.json            // Bookmarks just for users with a SIM card of a French operator&lt;br /&gt;
  ├── 262                           // 262 = Country code of Germany&lt;br /&gt;
  │   └── 01                        // 01 = Network code of &amp;quot;Deutsche Telekom&amp;quot;&lt;br /&gt;
  │       ├── bookmarks.json        // Bookmarks..&lt;br /&gt;
  │       └── preferences.json      // ... and preferences just for users of a SIM card of &amp;quot;Deutsche Telekom&amp;quot;&lt;br /&gt;
  └── default                       // Default folder&lt;br /&gt;
      └── preferences.json          // Preferences for all users with different SIM cards.&lt;br /&gt;
&lt;br /&gt;
== Partner Content Providers ==&lt;br /&gt;
&lt;br /&gt;
Android system images can ship with two content providers to customize installed browsers:&lt;br /&gt;
* content://com.android.partnerbookmarks - For partner bookmarks&lt;br /&gt;
* content://com.android.partnerbrowsercustomizations - For customizations (Details see below)&lt;br /&gt;
&lt;br /&gt;
Firefox for Android supports reading data from both of those content providers (Starting with Firefox for Android 50.0) if this has been enabled by a distribution. If the following preferences are not written by a distribution then Firefox for Android will ignore the data from the partner content providers.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;/distribution/preferences.json:&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[..]&lt;br /&gt;
  &amp;quot;AndroidPreferences&amp;quot;: {&lt;br /&gt;
    &amp;quot;distribution.read_partner_bookmarks_provider&amp;quot;: true,&lt;br /&gt;
    &amp;quot;distribution.read_partner_customizations_provider&amp;quot;: true&lt;br /&gt;
  }&lt;br /&gt;
[..]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bookmarks Content Provider ===&lt;br /&gt;
&lt;br /&gt;
Firefox for Android (&amp;gt;= 50.0) supports reading bookmarks and folders from the content provider. Reading icons from the content provider is currently not supported (See {{bug|1286203}}). Editing and deleting bookmarks/folders is not supported yet but planned.&lt;br /&gt;
&lt;br /&gt;
An example implementation of the content provider can be found in the official Android source tree:&lt;br /&gt;
* https://android.googlesource.com/platform/packages/providers/PartnerBookmarksProvider/+/master/src/com/android/providers/partnerbookmarks/PartnerBookmarksProvider.java&lt;br /&gt;
&lt;br /&gt;
=== Customizations Content Provider ===&lt;br /&gt;
&lt;br /&gt;
Firefox for Android (&amp;gt;= 50.0) only supports reading the &#039;homepage&#039; from the content provider. All other values are ignored.&lt;br /&gt;
&lt;br /&gt;
content://com.android.partnerbrowsercustomizations&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Path !! Column !! Supported&lt;br /&gt;
|-&lt;br /&gt;
| /homepage || homepage || Yes&lt;br /&gt;
|-&lt;br /&gt;
| /disableincognitomode || disableincognitomode || No&lt;br /&gt;
|-&lt;br /&gt;
| /disablebookmarksediting || disablebookmarksediting || No&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Testing ===&lt;br /&gt;
&lt;br /&gt;
There&#039;s a test app with sample data available on GitHub:&lt;br /&gt;
* https://github.com/pocmo/BrowserPartner&lt;br /&gt;
&lt;br /&gt;
The test app uses slightly different content provider authorities to allow being installed on devices that already ship with partner content providers:&lt;br /&gt;
&lt;br /&gt;
* com.android.partnerbookmarks.&#039;&#039;&#039;&#039;&#039;test&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
* com.android.partnerbrowsercustomizations.&#039;&#039;&#039;&#039;&#039;test&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A custom Firefox build is required to read from the test content providers.&lt;/div&gt;</summary>
		<author><name>Nevin</name></author>
	</entry>
</feed>