merge fx-team to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2014-11-11 13:13:34 +01:00
Родитель ee596ffa2e 3baff77d36
Коммит c3888e9dfc
34 изменённых файлов: 1010 добавлений и 226 удалений

Просмотреть файл

@ -509,8 +509,8 @@ SocialShare = {
iframe.setAttribute("disableglobalhistory", "true");
iframe.setAttribute("flex", "1");
panel.appendChild(iframe);
iframe.addEventListener("DOMContentLoaded", function _firstload() {
iframe.removeEventListener("DOMContentLoaded", _firstload, true);
iframe.addEventListener("load", function _firstload() {
iframe.removeEventListener("load", _firstload, true);
iframe.messageManager.loadFrameScript("chrome://browser/content/content.js", true);
}, true);
this.populateProviderMenu();

Просмотреть файл

@ -94,6 +94,15 @@ this.BingTranslator.prototype = {
}.bind(this));
},
/**
* Resets the expiration time of the current token, in order to
* force the token manager to ask for a new token during the next request.
*/
_resetToken : function() {
// Force the token manager to get update token
BingTokenManager._currentExpiryTime = 0;
},
/**
* Function called when a request sent to the server completed successfully.
* This function handles calling the function to parse the result and the
@ -115,17 +124,19 @@ this.BingTranslator.prototype = {
/**
* Function called when a request sent to the server has failed.
* This function handles deciding if the error is transient or means the
* service is unavailable (zero balance on the key) and calling the
* function to resolve the promise returned by the public `translate()`
* method when there's no pending request left.
* service is unavailable (zero balance on the key or request credentials are
* not in an active state) and calling the function to resolve the promise
* returned by the public `translate()` method when there's no pending.
* request left.
*
* @param aError [optional] The RESTRequest that failed.
*/
_chunkFailed: function(aError) {
if (aError instanceof RESTRequest &&
aError.response.status == 400) {
[400, 401].indexOf(aError.response.status) != -1) {
let body = aError.response.body;
if (body.contains("TranslateApiException") && body.contains("balance"))
if (body.contains("TranslateApiException") &&
(body.contains("balance") || body.contains("active state")))
this._serviceUnavailable = true;
}

Просмотреть файл

@ -128,6 +128,13 @@ function checkAuth(req) {
let auth = req.getHeader("Authorization");
if (!auth.startsWith("Bearer "))
throw new HTTPError(401, "Invalid Authorization header content: '" + auth + "'");
// Rejecting inactive subscriptions.
if (auth.contains("inactive")) {
const INACTIVE_STATE_RESPONSE = "<html><body><h1>TranslateApiException</h1><p>Method: TranslateArray()</p><p>Message: The Azure Market Place Translator Subscription associated with the request credentials is not in an active state.</p><code></code><p>message id=5641.V2_Rest.TranslateArray.48CC6470</p></body></html>";
throw new HTTPError(401, INACTIVE_STATE_RESPONSE);
}
}
function reallyHandleRequest(req, res) {
@ -189,8 +196,17 @@ const methodHandlers = {
return;
}
// Defines the tokens for certain client ids.
const TOKEN_MAP = {
'testInactive' : 'inactive',
'testClient' : 'test'
};
let token = 'test'; // Default token.
if((params.client_id in TOKEN_MAP)){
token = TOKEN_MAP[params.client_id];
}
let content = JSON.stringify({
access_token: "test",
access_token: token,
expires_in: 600
});

Просмотреть файл

@ -11,46 +11,111 @@ const kClientSecretPref = "browser.translation.bing.apiKeyOverride";
const {BingTranslator} = Cu.import("resource:///modules/translation/BingTranslator.jsm", {});
const {TranslationDocument} = Cu.import("resource:///modules/translation/TranslationDocument.jsm", {});
const {Promise} = Cu.import("resource://gre/modules/Promise.jsm", {});
function test() {
waitForExplicitFinish();
add_task(function* setup() {
Services.prefs.setCharPref(kClientIdPref, "testClient");
Services.prefs.setCharPref(kClientSecretPref, "testSecret");
registerCleanupFunction(function () {
Services.prefs.clearUserPref(kClientIdPref);
Services.prefs.clearUserPref(kClientSecretPref);
});
});
/**
* Checks if the translation is happening.
*/
add_task(function* test_bing_translation() {
// Ensure the correct client id is used for authentication.
Services.prefs.setCharPref(kClientIdPref, "testClient");
// Loading the fixture page.
let url = constructFixtureURL("bug1022725-fr.html");
let tab = yield promiseTestPageLoad(url);
// Translating the contents of the loaded tab.
gBrowser.selectedTab = tab;
let browser = tab.linkedBrowser;
let client = new BingTranslator(
new TranslationDocument(browser.contentDocument), "fr", "en");
let result = yield client.translate();
// XXXmikedeboer; here you would continue the test/ content inspection.
Assert.ok(result, "There should be a result.");
gBrowser.removeTab(tab);
});
/**
* Ensures that the BingTranslator handles out-of-valid-key response
* correctly. Sometimes Bing Translate replies with
* "request credentials is not in an active state" error. BingTranslator
* should catch this error and classify it as Service Unavailable.
*
*/
add_task(function* test_handling_out_of_valid_key_error() {
// Simulating request from inactive subscription.
Services.prefs.setCharPref(kClientIdPref, "testInactive");
// Loading the fixture page.
let url = constructFixtureURL("bug1022725-fr.html");
let tab = yield promiseTestPageLoad(url);
// Translating the contents of the loaded tab.
gBrowser.selectedTab = tab;
let browser = tab.linkedBrowser;
let client = new BingTranslator(
new TranslationDocument(browser.contentDocument), "fr", "en");
client._resetToken();
try {
yield client.translate();
} catch (ex) {
// It is alright that the translation fails.
}
client._resetToken();
// Checking if the client detected service and unavailable.
Assert.ok(client._serviceUnavailable, "Service should be detected unavailable.");
// Cleaning up.
Services.prefs.setCharPref(kClientIdPref, "testClient");
gBrowser.removeTab(tab);
});
/**
* A helper function for constructing a URL to a page stored in the
* local fixture folder.
*
* @param filename Name of a fixture file.
*/
function constructFixtureURL(filename){
// Deduce the Mochitest server address in use from a pref that was pre-processed.
let server = Services.prefs.getCharPref("browser.translation.bing.authURL")
.replace("http://", "");
server = server.substr(0, server.indexOf("/"));
let tab = gBrowser.addTab("http://" + server +
"/browser/browser/components/translation/test/fixtures/bug1022725-fr.html");
gBrowser.selectedTab = tab;
let url = "http://" + server +
"/browser/browser/components/translation/test/fixtures/" + filename;
return url;
}
registerCleanupFunction(function () {
gBrowser.removeTab(tab);
Services.prefs.clearUserPref(kClientIdPref);
Services.prefs.clearUserPref(kClientSecretPref);
});
let browser = tab.linkedBrowser;
browser.addEventListener("load", function onload() {
/**
* A helper function to open a new tab and wait for its content to load.
*
* @param String url A URL to be loaded in the new tab.
*/
function promiseTestPageLoad(url) {
let deferred = Promise.defer();
let tab = gBrowser.selectedTab = gBrowser.addTab(url);
let browser = gBrowser.selectedBrowser;
browser.addEventListener("load", function listener() {
if (browser.currentURI.spec == "about:blank")
return;
browser.removeEventListener("load", onload, true);
let client = new BingTranslator(
new TranslationDocument(browser.contentDocument), "fr", "en");
client.translate().then(
result => {
// XXXmikedeboer; here you would continue the test/ content inspection.
ok(result, "There should be a result.");
finish();
},
error => {
ok(false, "Unexpected Client Error: " + error);
finish();
}
);
info("Page loaded: " + browser.currentURI.spec);
browser.removeEventListener("load", listener, true);
deferred.resolve(tab);
}, true);
return deferred.promise;
}

Просмотреть файл

@ -36,6 +36,7 @@
--tab-selection-box-shadow: 0 2px 0 #d7f1ff inset,
0 8px 3px -5px #2b82bf inset,
0 -1px 0 rgba(0,0,0,.2) inset;
--pinned-tab-glow: radial-gradient(22px at center calc(100% - 2px), rgba(76,158,217,0.9) 13%, rgba(0,0,0,0.4) 16%, transparent 70%);
/* Toolbar buttons */
--toolbarbutton-hover-background: rgba(25,33, 38,.6) linear-gradient(rgba(25,33,38,.6), rgba(25,33,38,.6)) padding-box;
@ -97,6 +98,8 @@
--tab-selection-box-shadow: 0 2px 0 #d7f1ff inset,
0 8px 3px -5px #319BDB inset,
0 -1px 0 #2A7CB1 inset;
--pinned-tab-glow: radial-gradient(22px at center calc(100% - 2px), rgba(76,158,217,0.9) 13%, transparent 16%);
/* Toolbar buttons */
--toolbarbutton-hover-background: #D7D7D8;
@ -281,7 +284,7 @@ window:not([chromehidden~="toolbar"]) #urlbar-wrapper {
.tabbrowser-tab[pinned][titlechanged]:not([selected="true"]) > .tab-stack > .tab-content {
/* The -2px in `calc` is the height of `tabToolbarNavbarOverlap` plus a 1px offset from the center */
background-image: radial-gradient(22px at center calc(100% - 2px), rgba(76,158,217,0.9) 13%, rgba(0,0,0,0.4) 16%, rgba(29,79,115,0) 70%);
background-image: var(--pinned-tab-glow);
background-position: center;
background-size: 100%;
}

Просмотреть файл

@ -469,9 +469,7 @@ child:
RealKeyEvent(WidgetKeyboardEvent event, MaybeNativeKeyBinding keyBinding);
MouseWheelEvent(WidgetWheelEvent event);
RealTouchEvent(WidgetTouchEvent aEvent, ScrollableLayerGuid aGuid, uint64_t aInputBlockId);
// We use a separate message for touchmove events only to apply
// compression to them.
RealTouchMoveEvent(WidgetTouchEvent aEvent, ScrollableLayerGuid aGuid, uint64_t aInputBlockId) compress;
RealTouchMoveEvent(WidgetTouchEvent aEvent, ScrollableLayerGuid aGuid, uint64_t aInputBlockId);
/**
* @see nsIDOMWindowUtils sendKeyEvent.

Просмотреть файл

@ -583,6 +583,19 @@ MessageChannel::ShouldDeferMessage(const Message& aMsg)
return mSide == ParentSide && aMsg.transaction_id() != mCurrentTransaction;
}
// Predicate that is true for messages that should be consolidated if 'compress' is set.
class MatchingKinds {
typedef IPC::Message Message;
Message::msgid_t mType;
int32_t mRoutingId;
public:
MatchingKinds(Message::msgid_t aType, int32_t aRoutingId) :
mType(aType), mRoutingId(aRoutingId) {}
bool operator()(const Message &msg) {
return msg.type() == mType && msg.routing_id() == mRoutingId;
}
};
void
MessageChannel::OnMessageReceivedFromLink(const Message& aMsg)
{
@ -604,15 +617,22 @@ MessageChannel::OnMessageReceivedFromLink(const Message& aMsg)
// Prioritized messages cannot be compressed.
MOZ_ASSERT(!aMsg.compress() || aMsg.priority() == IPC::Message::PRIORITY_NORMAL);
bool compress = (aMsg.compress() && !mPending.empty() &&
mPending.back().type() == aMsg.type() &&
mPending.back().routing_id() == aMsg.routing_id());
bool compress = (aMsg.compress() && !mPending.empty());
if (compress) {
// This message type has compression enabled, and the back of the
// queue was the same message type and routed to the same destination.
// Replace it with the newer message.
MOZ_ASSERT(mPending.back().compress());
mPending.pop_back();
// Check the message queue for another message with this type/destination.
auto it = std::find_if(mPending.rbegin(), mPending.rend(),
MatchingKinds(aMsg.type(), aMsg.routing_id()));
if (it != mPending.rend()) {
// This message type has compression enabled, and the queue holds
// a message with the same message type and routed to the same destination.
// Erase it. Note that, since we always compress these redundancies, There Can
// Be Only One.
MOZ_ASSERT((*it).compress());
mPending.erase((++it).base());
} else {
// No other messages with the same type/destination exist.
compress = false;
}
}
bool shouldWakeUp = AwaitingInterruptReply() ||

Просмотреть файл

@ -0,0 +1,61 @@
project.buildDir = "${topobjdir}/mobile/android/gradle/app/build"
apply plugin: 'android'
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
}
buildTypes {
release {
runProguard false
proguardFile getDefaultProguardFile('proguard-android.txt')
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
android {
lintOptions {
abortOnError false
}
}
sourceSets {
main {
manifest {
srcFile "${topobjdir}/mobile/android/base/AndroidManifest.xml"
}
assets {
srcDir "${topobjdir}/dist/fennec/assets"
}
jniLibs {
srcDir "${topobjdir}/dist/fennec/lib"
}
}
androidTest {
java {
srcDir "${topobjdir}/mobile/android/gradle/app/src/androidTest/robocop_harness/java"
srcDir "${topobjdir}/mobile/android/gradle/app/src/androidTest/robocop/java"
srcDir "${topobjdir}/mobile/android/gradle/app/src/androidTest/background/java"
srcDir "${topobjdir}/mobile/android/gradle/app/src/androidTest/browser/java"
}
}
}
}
dependencies {
compile project(':base')
androidTestCompile fileTree(dir: "../../../build/mobile/robocop", include: ['*.jar'])
}

Просмотреть файл

@ -9,6 +9,7 @@ import org.mozilla.gecko.util.GeckoRequest;
import org.mozilla.gecko.util.NativeJSObject;
import org.mozilla.gecko.util.ThreadUtils;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.Context;
@ -21,15 +22,17 @@ import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.CheckedTextView;
import android.widget.LinearLayout;
import android.widget.TextView;
public class FindInPageBar extends LinearLayout implements TextWatcher, View.OnClickListener, GeckoEventListener {
private static final String LOGTAG = "FindInPageBar";
private static final String LOGTAG = "GeckoFindInPageBar";
private static final String REQUEST_ID = "FindInPageBar";
private final Context mContext;
private CustomEditText mFindText;
private CheckedTextView mMatchCase;
private TextView mStatusText;
private boolean mInflated;
@ -64,6 +67,9 @@ public class FindInPageBar extends LinearLayout implements TextWatcher, View.OnC
}
});
mMatchCase = (CheckedTextView) content.findViewById(R.id.find_matchcase);
mMatchCase.setOnClickListener(this);
mStatusText = (TextView) content.findViewById(R.id.find_status);
mInflated = true;
@ -123,6 +129,16 @@ public class FindInPageBar extends LinearLayout implements TextWatcher, View.OnC
public void onClick(View v) {
final int viewId = v.getId();
if (viewId == R.id.find_matchcase) {
// Toggle matchcase state (color).
mMatchCase.toggle();
// Repeat the find after a matchcase change.
sendRequestToFinderHelper("FindInPage:Find", mFindText.getText().toString());
getInputMethodManager(mFindText).hideSoftInputFromWindow(mFindText.getWindowToken(), 0);
return;
}
if (viewId == R.id.find_prev) {
sendRequestToFinderHelper("FindInPage:Prev", mFindText.getText().toString());
getInputMethodManager(mFindText).hideSoftInputFromWindow(mFindText.getWindowToken(), 0);
@ -184,7 +200,16 @@ public class FindInPageBar extends LinearLayout implements TextWatcher, View.OnC
* Request find operation, and update matchCount results (current count and total).
*/
private void sendRequestToFinderHelper(final String request, final String searchString) {
GeckoAppShell.sendRequestToGecko(new GeckoRequest(request, searchString) {
final JSONObject json = new JSONObject();
try {
json.put("searchString", searchString);
json.put("matchCase", mMatchCase.isChecked());
} catch (JSONException e) {
Log.e(LOGTAG, "JSON error - Error creating JSONObject", e);
return;
}
GeckoAppShell.sendRequestToGecko(new GeckoRequest(request, json) {
@Override
public void onResponse(NativeJSObject nativeJSObject) {
final int total = nativeJSObject.optInt("total", 0);

Просмотреть файл

@ -397,10 +397,10 @@ fennec_ids.txt: generated/org/mozilla/gecko/R.java fennec-ids-generator.py
# Override the Java settings with some specific android settings
include $(topsrcdir)/config/android-common.mk
# This target is only used by the Eclipse integration. It rebuilds
# resources that end up in omni.ja, does most of the packaging step,
# and then updates omni.ja in place. If you're not using Eclipse, you
# should be using |mach build mobile/android && mach package|.
# This target is only used by IDE integrations. It rebuilds resources
# that end up in omni.ja, does most of the packaging step, and then
# updates omni.ja in place. If you're not using an IDE, you should be
# using |mach build mobile/android && mach package|.
$(abspath $(DIST)/fennec/$(OMNIJAR_NAME)): FORCE
$(REPORT_BUILD)
$(MAKE) -C ../locales
@ -413,6 +413,12 @@ $(abspath $(DIST)/fennec/$(OMNIJAR_NAME)): FORCE
rsync --update $(DIST)/fennec/$(notdir $(OMNIJAR_NAME)) $@
$(RM) $(DIST)/fennec/$(notdir $(OMNIJAR_NAME))
# Targets built very early during a Gradle build.
gradle-targets: $(abspath $(DIST)/fennec/$(OMNIJAR_NAME))
gradle-targets: .aapt.deps
.PHONY: gradle-targets
libs:: geckoview_resources.zip classes.dex jni-stubs.inc GeneratedJNIWrappers.cpp fennec_ids.txt
$(INSTALL) geckoview_resources.zip $(FINAL_TARGET)
$(INSTALL) classes.dex $(FINAL_TARGET)

Просмотреть файл

@ -0,0 +1,98 @@
project.buildDir = "${topobjdir}/mobile/android/gradle/base/build"
apply plugin: 'android-library'
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
applicationId 'org.mozilla.gecko'
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
}
buildTypes {
release {
runProguard false
proguardFile getDefaultProguardFile('proguard-android.txt')
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
android {
lintOptions {
abortOnError false
}
}
sourceSets {
main {
manifest {
srcFile 'gradle_AndroidManifest.xml'
}
java {
// The main sources are symlinked in here.
srcDir "${topobjdir}/mobile/android/gradle/base/src/main/java"
exclude '**/tests/**'
exclude '**/resources/**'
if (!MOZ_CRASHREPORTER) {
exclude '**/CrashReporter.java'
}
srcDir "../search/java"
srcDir "../stumbler/java"
srcDir "${topobjdir}/mobile/android/base/generated"
exclude '**/R.java'
exclude '**/Manifest.java'
}
res {
srcDir "newtablet/res"
srcDir "../branding/unofficial/res"
srcDir "${topobjdir}/mobile/android/base/res"
// The main resources are symlinked in here.
srcDir "${topobjdir}/mobile/android/gradle/base/src/main/res"
if (MOZ_CRASHREPORTER) {
srcDir "crashreporter/res"
}
}
resources {
srcDir '../locales'
srcDir '../chrome'
srcDir '../components'
srcDir '../modules'
srcDir '../app'
srcDir '../themes/core'
}
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile project(':thirdparty')
compile 'com.android.support:support-v4:19.1.+'
compile 'com.android.support:appcompat-v7:19.1.+'
compile 'com.android.support:mediarouter-v7:19.1.+'
compile 'com.google.android.gms:play-services:5.+'
}
task prepareObjDir(type:Exec) {
workingDir "${topobjdir}"
commandLine "${topsrcdir}/mach"
args 'build'
args '-C'
args 'mobile/android/base'
args 'gradle-targets'
}
android.libraryVariants.all { variant ->
variant.checkManifest.dependsOn prepareObjDir
}

Просмотреть файл

@ -0,0 +1,98 @@
.. -*- Mode: rst; fill-column: 80; -*-
======================
Building with Gradle
======================
Instructions
============
.. code-block:: shell
./mach build && ./mach package
cd $OBJDIR/mobile/android
./gradlew build
The debug APK will be at
``$OBJDIR/mobile/android/gradle/app/build/outputs/apk/app-debug.apk``.
The ``$OBJDIR/mobile/android/gradle`` directory can be imported into IntelliJ as
follows:
- File > Import Project
- [select ``$OBJDIR/mobile/android/gradle``]
- Import project from external model > Gradle
- [select Use default Gradle wrapper]
When prompted, do not add any files to git. You may need to re-open the
project, or restart IntelliJ, to pick up a compiler language-level change.
Technical overview
==================
Caveats
-------
* The Gradle build will "succeed" but crash on start up if the object directory
has not been properly packaged.
* Changes to preprocessed source code and resources (namely, ``strings.xml.in``
and the accompanying DTD files) may not be recognized.
* There's minimal support for editing JavaScript.
* There's no support for editing C/C++.
How the Gradle project is laid out
----------------------------------
To the greatest extent possible, the Gradle configuration lives in the source
directory. The only Gradle configuration that lives in the object directory is
installed when building the ``mobile/android/gradle`` directory.
At the time of writing, their are three sub-modules: *app*, *base*, and *thirdparty*.
*app* is the Fennec wrapper; it generates the **org.mozilla.fennec.R** resource
package. *base* is the Gecko code; it generates the **org.mozilla.gecko.R**
resource package. Together, *app* and *base* address the "two package
namespaces" that has plagued Fennec from day one.
Due to limitations in the Android Gradle plugin, all test code is shoved into
the *app* module. (The issue is that, at the time of writing, there is no
support for test-only APKs.) For no particular reason, the compiled C/C++
libraries are included in the *app* module; they could be included in the *base*
module. I expect *base* to rebuilt slightly more frequently than *app*, so I'm
hoping this choice will allow for faster incremental builds.
*thirdparty* is the external code we use in Fennec; it's built as an Android
library but uses no resources. It's separate simply to allow the build system
to cache the compiled and pre-dexed artifacts, hopefully allowing for faster
incremental builds.
Recursive make backend details
------------------------------
The ``mobile/android/gradle`` directory writes the following into
``$OBJDIR/mobile/android/gradle``:
1) the Gradle wrapper;
2) ``gradle.properties``;
3) symlinks to certain source and resource directories.
The Gradle wrapper is written to make it easy to build with Gradle from the
object directory. The wrapper is `intended to be checked into version
control`_.
``gradle.properties`` is the single source of per-object directory Gradle
configuration, and provides the Gradle configuration access to
configure/moz.build variables.
The symlinks are not necessary for the Gradle build itself, but they prevent
nested directory errors and incorrect Java package scoping when the Gradle
project is imported into IntelliJ. Because IntelliJ treats the Gradle project
as authoritative, it's not sufficient to fix these manually in IntelliJ after
the initial import -- IntelliJ reverts to the Gradle configuration after every
build. Since there aren't many symlinks, I've done them in the Makefile rather
than at a higher level of abstraction (like a moz.build definition, or a custom
build backend). In future, I expect to be able to remove all such symlinks by
making our in-tree directory structures agree with what Gradle and IntelliJ
expect.
.. _intended to be checked into version control: http://www.gradle.org/docs/current/userguide/gradle_wrapper.html

Просмотреть файл

@ -2,159 +2,9 @@
Firefox for Android
===================
UI Telemetry
============
.. toctree::
:maxdepth: 1
Fennec records UI events using a telemetry framework called UITelemetry.
Some links:
- `Project page <https://wiki.mozilla.org/Mobile/Projects/Telemetry_probes_for_Fennec_UI_elements>`_
- `Wiki page <https://wiki.mozilla.org/Mobile/Fennec/Android/UITelemetry>`_
- `User research notes <https://wiki.mozilla.org/Mobile/User_Experience/Research>`_
Sessions
========
**Sessions** are essentially scopes. They are meant to provide context to
events; this allows events to be simpler and more reusable. Sessions are
usually bound to some component of the UI, some user action with a duration, or
some transient state.
For example, a session might be begun when a user begins interacting with a
menu, and stopped when the interaction ends. Or a session might encapsulate
period of no network connectivity, the first five seconds after the browser
launched, the time spent with an active download, or a guest mode session.
Sessions implicitly record the duration of the interaction.
A simple use-case for sessions is the bookmarks panel in about:home. We start a
session when the user swipes into the panel, and stop it when they swipe away.
This bookmarks session does two things: firstly, it gives scope to any generic
event that may occur within the panel (*e.g.*, loading a URL). Secondly, it
allows us to figure out how much time users are spending in the bookmarks
panel.
To start a session, call ``Telemetry.startUISession(String sessionName)``.
``sessionName``
The name of the session. Session names should be brief, lowercase, and should describe which UI
component the user is interacting with. In certain cases where the UI component is dynamic, they could include an ID, essential to identifying that component. An example of this is dynamic home panels: we use session names of the format ``homepanel:<panel_id>`` to identify home panel sessions.
To stop a session, call ``Telemetry.stopUISession(String sessionName, String reason)``.
``sessionName``
The name of the open session
``reason`` (Optional)
A descriptive cause for ending the session. It should be brief, lowercase, and generic so it can be reused in different places. Examples reasons are:
``switched``
The user transitioned to a UI element of equal level.
``exit``
The user left for an entirely different element.
Events
======
Events capture key occurrences. They should be brief and simple, and should not contain sensitive or excess information. Context for events should come from the session (scope). An event can be created with four fields (via ``Telemetry.sendUIEvent``): ``action``, ``method``, ``extras``, and ``timestamp``.
``action``
The name of the event. Should be brief and lowercase. If needed, you can make use of namespacing with a '``.``' separator. Example event names: ``panel.switch``, ``panel.enable``, ``panel.disable``, ``panel.install``.
``method`` (Optional)
Used for user actions that can be performed in many ways. This field specifies the method by which the action was performed. For example, users can add an item to their reading list either by long-tapping the reader icon in the address bar, or from within reader mode. We would use the same event name for both user actions but specify two methods: ``addressbar`` and ``readermode``.
``extras`` (Optional)
For extra information that may be useful in understanding the event. Make an effort to keep this brief.
``timestamp`` (Optional)
The time at which the event occurred. If not specified, this field defaults to the current value of the realtime clock.
Versioning
========
As a we improve on our Telemetry methods, it is foreseeable that our probes will change over time. Different versions of a probe could carry different data or have different interpretations on the server-side. To make it easier for the server to handle these changes, you should add version numbers to your event and session names. An example of a versioned session is ``homepanel.1``; this is version 1 of the ``homepanel`` session. This approach should also be applied to event names, an example being: ``panel.enable.1`` and ``panel.enable.2``.
Clock
=====
Times are relative to either elapsed realtime (an arbitrary monotonically increasing clock that continues to tick when the device is asleep), or elapsed uptime (which doesn't tick when the device is in deep sleep). We default to elapsed realtime.
See the documentation in `the source <http://mxr.mozilla.org/mozilla-central/source/mobile/android/base/Telemetry.java>`_ for more details.
Dictionary
==========
Events
------
``action.1``
Generic action, usually for tracking menu and toolbar actions.
``cancel.1``
Cancel a state, action, etc.
``cast.1``
Start casting a video.
``edit.1``
Sent when the user edits a top site.
``launch.1``
Launching (opening) an external application.
Note: Only used in JavaScript for now.
``loadurl.1``
Loading a URL.
``locale.browser.reset.1``
When the user chooses "System default" in the browser locale picker.
``locale.browser.selected.1``
When the user chooses a locale in the browser locale picker. The selected
locale is provided as the extra.
``locale.browser.unselected.1``
When the user chose a different locale in the browser locale picker, this
event is fired with the previous locale as the extra. If the previous locale
could not be determined, "unknown" is provided.
``setdefault.1``
Set default home panel.
``pin.1``, ``unpin.1``
Sent when the user pinned or unpinned a top site.
``policynotification.success.1:true``
Sent when a user has accepted the data notification policy. Can be ``false``
instead of ``true`` if an error occurs.
``sanitize.1``
Sent when the user chooses to clear private data.
``save.1`` ``unsave.1``
Saving or unsaving a resource (reader, bookmark, etc.) for viewing later.
Note: Only used in JavaScript for now.
``search.1``
Sent when the user performs a search. Currently used in the search activity.
``share.1``
Sharing content.
Methods
-------
``banner``
Action triggered from a banner (such as HomeBanner).
Note: Only used in JavaScript for now.
``content``
Action triggered from a content page.
Sessions
--------
``searchactivity.1``
Started when the user launches the search activity (onStart) and stopped
when they leave the search activity.
localeswitching
uitelemetry
gradle

Просмотреть файл

@ -1,6 +1,8 @@
==================================
Runtime locale switching in Fennec
==================================
.. -*- Mode: rst; fill-column: 80; -*-
====================================
Runtime locale switching in Fennec
====================================
`Bug 917480 <https://bugzilla.mozilla.org/show_bug.cgi?id=917480>`_ built on `Bug 936756 <https://bugzilla.mozilla.org/show_bug.cgi?id=936756>`_ to allow users to switch between supported locales at runtime, within Fennec, without altering the system locale.

Просмотреть файл

@ -0,0 +1,159 @@
.. -*- Mode: rst; fill-column: 80; -*-
==============
UI Telemetry
==============
Fennec records UI events using a telemetry framework called UITelemetry.
Some links:
- `Project page <https://wiki.mozilla.org/Mobile/Projects/Telemetry_probes_for_Fennec_UI_elements>`_
- `Wiki page <https://wiki.mozilla.org/Mobile/Fennec/Android/UITelemetry>`_
- `User research notes <https://wiki.mozilla.org/Mobile/User_Experience/Research>`_
Sessions
========
**Sessions** are essentially scopes. They are meant to provide context to
events; this allows events to be simpler and more reusable. Sessions are
usually bound to some component of the UI, some user action with a duration, or
some transient state.
For example, a session might be begun when a user begins interacting with a
menu, and stopped when the interaction ends. Or a session might encapsulate
period of no network connectivity, the first five seconds after the browser
launched, the time spent with an active download, or a guest mode session.
Sessions implicitly record the duration of the interaction.
A simple use-case for sessions is the bookmarks panel in about:home. We start a
session when the user swipes into the panel, and stop it when they swipe away.
This bookmarks session does two things: firstly, it gives scope to any generic
event that may occur within the panel (*e.g.*, loading a URL). Secondly, it
allows us to figure out how much time users are spending in the bookmarks
panel.
To start a session, call ``Telemetry.startUISession(String sessionName)``.
``sessionName``
The name of the session. Session names should be brief, lowercase, and should describe which UI
component the user is interacting with. In certain cases where the UI component is dynamic, they could include an ID, essential to identifying that component. An example of this is dynamic home panels: we use session names of the format ``homepanel:<panel_id>`` to identify home panel sessions.
To stop a session, call ``Telemetry.stopUISession(String sessionName, String reason)``.
``sessionName``
The name of the open session
``reason`` (Optional)
A descriptive cause for ending the session. It should be brief, lowercase, and generic so it can be reused in different places. Examples reasons are:
``switched``
The user transitioned to a UI element of equal level.
``exit``
The user left for an entirely different element.
Events
======
Events capture key occurrences. They should be brief and simple, and should not contain sensitive or excess information. Context for events should come from the session (scope). An event can be created with four fields (via ``Telemetry.sendUIEvent``): ``action``, ``method``, ``extras``, and ``timestamp``.
``action``
The name of the event. Should be brief and lowercase. If needed, you can make use of namespacing with a '``.``' separator. Example event names: ``panel.switch``, ``panel.enable``, ``panel.disable``, ``panel.install``.
``method`` (Optional)
Used for user actions that can be performed in many ways. This field specifies the method by which the action was performed. For example, users can add an item to their reading list either by long-tapping the reader icon in the address bar, or from within reader mode. We would use the same event name for both user actions but specify two methods: ``addressbar`` and ``readermode``.
``extras`` (Optional)
For extra information that may be useful in understanding the event. Make an effort to keep this brief.
``timestamp`` (Optional)
The time at which the event occurred. If not specified, this field defaults to the current value of the realtime clock.
Versioning
========
As a we improve on our Telemetry methods, it is foreseeable that our probes will change over time. Different versions of a probe could carry different data or have different interpretations on the server-side. To make it easier for the server to handle these changes, you should add version numbers to your event and session names. An example of a versioned session is ``homepanel.1``; this is version 1 of the ``homepanel`` session. This approach should also be applied to event names, an example being: ``panel.enable.1`` and ``panel.enable.2``.
Clock
=====
Times are relative to either elapsed realtime (an arbitrary monotonically increasing clock that continues to tick when the device is asleep), or elapsed uptime (which doesn't tick when the device is in deep sleep). We default to elapsed realtime.
See the documentation in `the source <http://mxr.mozilla.org/mozilla-central/source/mobile/android/base/Telemetry.java>`_ for more details.
Dictionary
==========
Events
------
``action.1``
Generic action, usually for tracking menu and toolbar actions.
``cancel.1``
Cancel a state, action, etc.
``cast.1``
Start casting a video.
``edit.1``
Sent when the user edits a top site.
``launch.1``
Launching (opening) an external application.
Note: Only used in JavaScript for now.
``loadurl.1``
Loading a URL.
``locale.browser.reset.1``
When the user chooses "System default" in the browser locale picker.
``locale.browser.selected.1``
When the user chooses a locale in the browser locale picker. The selected
locale is provided as the extra.
``locale.browser.unselected.1``
When the user chose a different locale in the browser locale picker, this
event is fired with the previous locale as the extra. If the previous locale
could not be determined, "unknown" is provided.
``setdefault.1``
Set default home panel.
``pin.1``, ``unpin.1``
Sent when the user pinned or unpinned a top site.
``policynotification.success.1:true``
Sent when a user has accepted the data notification policy. Can be ``false``
instead of ``true`` if an error occurs.
``sanitize.1``
Sent when the user chooses to clear private data.
``save.1`` ``unsave.1``
Saving or unsaving a resource (reader, bookmark, etc.) for viewing later.
Note: Only used in JavaScript for now.
``search.1``
Sent when the user performs a search. Currently used in the search activity.
``share.1``
Sharing content.
Methods
-------
``banner``
Action triggered from a banner (such as HomeBanner).
Note: Only used in JavaScript for now.
``content``
Action triggered from a content page.
Sessions
--------
``searchactivity.1``
Started when the user launches the search activity (onStart) and stopped
when they leave the search activity.

Просмотреть файл

@ -0,0 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.mozilla.gecko">
</manifest>

Просмотреть файл

@ -557,3 +557,8 @@ just addresses the organization to follow, e.g. "This site is run by " -->
"Last synced" is one of the user's other Sync clients, typically Firefox on
their desktop or laptop.-->
<!ENTITY remote_tabs_last_synced "Last synced: &formatS;">
<!-- Find-In-Page strings -->
<!-- LOCALIZATION NOTE (find_matchcase): This is meant to appear as an icon that changes color
if match-case is activated. i.e. No more than two letters, one uppercase, one lowercase. -->
<!ENTITY find_matchcase "Aa">

Просмотреть файл

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true"
android:color="@color/find_matchcase_on"/>
<item android:state_checked="false"
android:color="@color/find_matchcase_off"/>
</selector>

Просмотреть файл

@ -28,6 +28,15 @@
android:textColor="@color/find_status_default"
android:visibility="gone"/>
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/find_matchcase"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="@dimen/find_in_page_matchcase_margin_right"
android:checked="false"
android:text="@string/find_matchcase"
android:textColor="@drawable/find_matchcase_selector"/>
<ImageButton android:id="@+id/find_prev"
style="@style/FindBar.ImageButton"
android:contentDescription="@string/find_prev"

Просмотреть файл

@ -152,6 +152,8 @@
<!-- Colour used for Find-In-Page dialog -->
<color name="find_status_default">#AFB1B3</color>
<color name="find_matchcase_on">#AFB1B3</color>
<color name="find_matchcase_off">#D02626</color>
<!-- Canvas delegate paint color -->
<color name="canvas_delegate_paint">#FFFF0000</color>

Просмотреть файл

@ -183,7 +183,8 @@
<dimen name="find_in_page_text_margin_right">12dip</dimen>
<dimen name="find_in_page_text_padding_left">10dip</dimen>
<dimen name="find_in_page_text_padding_right">10dip</dimen>
<dimen name="find_in_page_status_margin_right">5dip</dimen>
<dimen name="find_in_page_status_margin_right">15dip</dimen>
<dimen name="find_in_page_matchcase_margin_right">10dip</dimen>
<dimen name="find_in_page_control_margin_top">2dip</dimen>
</resources>

Просмотреть файл

@ -33,18 +33,18 @@ var FindHelper = {
_findOpened: function() {
Messaging.addListener((data) => {
this.doFind(data);
return this._getMatchesCountResult(data);
this.doFind(data.searchString, data.matchCase);
return this._getMatchesCountResult(data.searchString);
}, "FindInPage:Find");
Messaging.addListener((data) => {
this.findAgain(data, false);
return this._getMatchesCountResult(data);
this.findAgain(data.searchString, false, data.matchCase);
return this._getMatchesCountResult(data.searchString);
}, "FindInPage:Next");
Messaging.addListener((data) => {
this.findAgain(data, true);
return this._getMatchesCountResult(data);
this.findAgain(data.searchString, true, data.matchCase);
return this._getMatchesCountResult(data.searchString);
}, "FindInPage:Prev");
},
@ -99,22 +99,24 @@ var FindHelper = {
this._matchesCountResult = result;
},
doFind: function(aSearchString) {
doFind: function(searchString, matchCase) {
if (!this._finder) {
this._init();
}
this._finder.fastFind(aSearchString, false);
this._finder.caseSensitive = matchCase;
this._finder.fastFind(searchString, false);
},
findAgain: function(aString, aFindBackwards) {
findAgain: function(searchString, findBackwards, matchCase) {
// This can happen if the user taps next/previous after re-opening the search bar
if (!this._finder) {
this.doFind(aString);
this.doFind(searchString, matchCase);
return;
}
this._finder.findAgain(aFindBackwards, false, false);
this._finder.caseSensitive = matchCase;
this._finder.findAgain(findBackwards, false, false);
},
onFindResult: function(aData) {

Просмотреть файл

@ -0,0 +1,57 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
gradle := \
gradle.properties.in \
$(NULL)
gradle_PATH := $(CURDIR)
gradle_FLAGS += -Dtopsrcdir=$(abspath $(topsrcdir))
gradle_FLAGS += -Dtopobjdir=$(abspath $(DEPTH))
gradle_KEEP_PATH := 1
PP_TARGETS += gradle
wrapper_FILES := \
build.gradle \
settings.gradle \
gradle/wrapper/gradle-wrapper.jar \
gradle/wrapper/gradle-wrapper.properties \
gradlew \
$(NULL)
wrapper_DEST := $(CURDIR)
wrapper_KEEP_PATH := 1
INSTALL_TARGETS += wrapper
base/src/main/java/org/mozilla/gecko:
$(NSINSTALL) -D ${@D}
ln -s $(topsrcdir)/mobile/android/base $@
libs:: base/src/main/java/org/mozilla/gecko
base/src/main/res:
$(NSINSTALL) -D ${@D}
ln -s $(topsrcdir)/mobile/android/base/resources $@
libs:: base/src/main/res
app/src/androidTest/robocop_harness/java/org/mozilla/gecko:
$(NSINSTALL) -D ${@D}
ln -s $(topsrcdir)/build/mobile/robocop $@
libs:: app/src/androidTest/robocop_harness/java/org/mozilla/gecko
app/src/androidTest/robocop/java/org/mozilla/gecko/tests:
$(NSINSTALL) -D ${@D}
ln -s $(topsrcdir)/mobile/android/base/tests $@
libs:: app/src/androidTest/robocop/java/org/mozilla/gecko/tests
app/src/androidTest/browser/java/org/mozilla/gecko:
$(NSINSTALL) -D ${@D}
ln -s $(topsrcdir)/mobile/android/tests/browser/junit3/src $@
libs:: app/src/androidTest/browser/java/org/mozilla/gecko
app/src/androidTest/background/java/org/mozilla/gecko/background:
$(NSINSTALL) -D ${@D}
ln -s $(topsrcdir)/mobile/android/tests/background/junit3/src $@
libs:: app/src/androidTest/background/java/org/mozilla/gecko/background
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -0,0 +1,23 @@
buildDir = "${topobjdir}/mobile/android/gradle/build"
ext {
compileSdkVersion = "${compileSdkVersion}"
buildToolsVersion = "${buildToolsVersion}"
targetSdkVersion = "${targetSdkVersion}"
minSdkVersion = "${minSdkVersion}"
}
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.12.2'
}
}
repositories {
jcenter()
}

Просмотреть файл

@ -0,0 +1,15 @@
#filter substitution
topsrcdir=@topsrcdir@
topobjdir=@topobjdir@
compileSdkVersion=android-@ANDROID_TARGET_SDK@
buildToolsVersion=20.0.0
targetSdkVersion=@ANDROID_TARGET_SDK@
minSdkVersion=@MOZ_ANDROID_MIN_SDK_VERSION@
#ifdef MOZ_ANDROID_MAX_SDK_VERSION
maxSdkVersion=@MOZ_ANDROID_MAX_SDK_VERSION@
#endif
#if MOZ_CRASHREPORTER
MOZ_CRASHREPORTER=true
#else
MOZ_CRASHREPORTER=false
#endif

Двоичные данные
mobile/android/gradle/gradle/wrapper/gradle-wrapper.jar поставляемый Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,6 @@
#Wed Apr 10 15:27:10 PDT 2013
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=http\://services.gradle.org/distributions/gradle-1.12-all.zip

164
mobile/android/gradle/gradlew поставляемый Executable file
Просмотреть файл

@ -0,0 +1,164 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

Просмотреть файл

@ -0,0 +1,5 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

Просмотреть файл

@ -0,0 +1,8 @@
include ':app'
project(':app').projectDir = new File("${topsrcdir}/mobile/android/app")
include ':base'
project(':base').projectDir = new File("${topsrcdir}/mobile/android/base")
include ':thirdparty'
project(':thirdparty').projectDir = new File("${topsrcdir}/mobile/android/thirdparty")

Просмотреть файл

@ -24,6 +24,7 @@ DIRS += [
'fonts',
'geckoview_library',
'extensions',
'gradle',
]
if not CONFIG['LIBXUL_SDK']:

Просмотреть файл

@ -216,3 +216,6 @@
<string name="fxaccount_remove_account_dialog_message">&fxaccount_remove_account_dialog_message;</string>
<string name="fxaccount_remove_account_toast">&fxaccount_remove_account_toast;</string>
<string name="fxaccount_remove_account_menu_item">&fxaccount_remove_account_menu_item;</string>
<!-- Find-In-Page strings -->
<string name="find_matchcase">&find_matchcase;</string>

49
mobile/android/thirdparty/build.gradle поставляемый Normal file
Просмотреть файл

@ -0,0 +1,49 @@
project.buildDir = "${topobjdir}/mobile/android/gradle/thirdparty/build"
apply plugin: 'android-library'
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
applicationId 'org.mozilla.gecko.thirdparty'
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
}
buildTypes {
release {
runProguard false
proguardFile getDefaultProguardFile('proguard-android.txt')
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
android {
lintOptions {
abortOnError false
}
}
sourceSets {
main {
manifest {
srcFile 'gradle_AndroidManifest.xml'
}
java {
srcDir "."
}
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:support-v4:19.1.+'
}

4
mobile/android/thirdparty/gradle_AndroidManifest.xml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.mozilla.gecko.thirdparty">
</manifest>