зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 141fda86ce58 (bug 1639180
) for causing rst lint failures.
CLOSED TREE
This commit is contained in:
Родитель
6d165c571f
Коммит
e9d51d0f4d
|
@ -0,0 +1,10 @@
|
|||
source "https://rubygems.org"
|
||||
|
||||
|
||||
# This is the default theme for new Jekyll sites. You may change this to anything you like.
|
||||
gem "just-the-docs"
|
||||
|
||||
# If you want to use GitHub Pages, remove the "gem "jekyll"" above and
|
||||
# uncomment the line below. To upgrade, run `bundle update github-pages`.
|
||||
gem "github-pages", group: :jekyll_plugins
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
title: GeckoView
|
||||
email: etoop@mozilla.com
|
||||
description:
|
||||
The privacy focused WebView you've been looking for.
|
||||
baseurl: "/geckoview" # the subpath of your site, e.g. /blog
|
||||
url: "https://mozilla.github.io" # the base hostname & protocol for your site, e.g. http://example.com
|
||||
twitter_username: geckoview
|
||||
github_username: mozilla
|
||||
tags: [GeckoView,Gecko,mozilla,android,WebView,web,browser,toolkit,open source,privacy,online,security,mobile]
|
||||
|
||||
# Build settings
|
||||
markdown: kramdown
|
||||
remote_theme: pmarsceill/just-the-docs@aa0d8f1d400b051c090b04b3e530c2848afb585c
|
||||
plugins:
|
||||
- jekyll-feed
|
||||
- jekyll-seo-tag
|
||||
|
||||
search_enabled: true
|
|
@ -0,0 +1,32 @@
|
|||
<head>
|
||||
<!-- 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/. -->
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
|
||||
{% if page.title %}
|
||||
<meta name="title" content="{{ page.title }} - {{ site.title }}">
|
||||
{% endif %}
|
||||
{% if page.description %}
|
||||
<meta name="description" content="{{ page.description }}">
|
||||
{% elsif page.summary %}
|
||||
<meta name="description" content="{{ page.summary }}">
|
||||
{% else %}
|
||||
<meta name="description" content="{{ site.description }}">
|
||||
{% endif %}
|
||||
{% if page.tags %}
|
||||
<meta name="keywords" content="{{ page.tags | join: "," }}">
|
||||
{% else %}
|
||||
<meta name="keywords" content="{{ site.tags | join: "," }}">
|
||||
{% endif %}
|
||||
|
||||
<title>{{ page.title }} - {{ site.title }}</title>
|
||||
<link rel="stylesheet" href="{{ "/assets/css/just-the-docs.css" | absolute_url }}">
|
||||
<link rel="stylesheet" href="{{ "/assets/css/geckoview.css" | absolute_url }}">
|
||||
{% if site.search_enabled != nil %}
|
||||
<script type="text/javascript" src="{{ "/assets/js/vendor/lunr.min.js" | absolute_url }}"></script>
|
||||
{% endif %}
|
||||
<script type="text/javascript" src="{{ "/assets/js/just-the-docs.js" | absolute_url }}"></script>
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
</head>
|
|
@ -0,0 +1,9 @@
|
|||
<!-- 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/. -->
|
||||
<li class="navigation-list-item{% if page.url contains '/javadoc/mozilla-central/index.html' %} active{% endif %}">
|
||||
<a href="{{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/index.html" class="navigation-list-link{% if page.url contains '/javadoc/mozilla-central/index.html' %} active{% endif %}">API Documentation</a>
|
||||
</li>
|
||||
<li class="navigation-list-item{% if page.url contains 'CHANGELOG' %} active{% endif %}">
|
||||
<a href="{{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/doc-files/CHANGELOG" class="navigation-list-link{% if page.url contains 'CHANGELOG' %} active{% endif %}">API Changelog</a>
|
||||
</li>
|
|
@ -0,0 +1,49 @@
|
|||
<!-- 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/. -->
|
||||
<nav role="navigation" aria-label="Main navigation">
|
||||
<ul class="navigation-list">
|
||||
{% assign pages_list = site.html_pages | sort:"nav_order" %}
|
||||
{% for node in pages_list %}
|
||||
<!-- <div>{{node.title}} = {{node.nav_exclude}}</div> -->
|
||||
{% unless node.nav_exclude %}
|
||||
{% if node.parent == nil %}
|
||||
<li class="navigation-list-item{% if page.url == node.url or page.parent == node.title or page.grand_parent == node.title %} active{% endif %}">
|
||||
{% if page.parent == node.title or page.grand_parent == node.title %}
|
||||
{% assign first_level_url = node.url | absolute_url %}
|
||||
{% endif %}
|
||||
<a href="{{ node.url | absolute_url }}" class="navigation-list-link{% if page.url == node.url %} active{% endif %}">{{ node.title }}</a>
|
||||
{% if node.has_children %}
|
||||
{% assign children_list = site.html_pages | sort:"nav_order" %}
|
||||
<ul class="navigation-list-child-list ">
|
||||
{% for child in children_list %}
|
||||
{% if child.parent == node.title %}
|
||||
<li class="navigation-list-item {% if page.url == child.url or page.parent == child.title %} active{% endif %}">
|
||||
{% if page.url == child.url or page.parent == child.title %}
|
||||
{% assign second_level_url = child.url | absolute_url %}
|
||||
{% endif %}
|
||||
<a href="{{ child.url | absolute_url }}" class="navigation-list-link{% if page.url == child.url %} active{% endif %}">{{ child.title }}</a>
|
||||
{% if child.has_children %}
|
||||
{% assign grand_children_list = site.html_pages | sort:"nav_order" %}
|
||||
<ul class="navigation-list-child-list">
|
||||
{% for grand_child in grand_children_list %}
|
||||
{% if grand_child.parent == child.title %}
|
||||
<li class="navigation-list-item {% if page.url == grand_child.url %} active{% endif %}">
|
||||
<a href="{{ grand_child.url | absolute_url }}" class="navigation-list-link{% if page.url == grand_child.url %} active{% endif %}">{{ grand_child.title }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endunless %}
|
||||
{% endfor %}
|
||||
{% include javadoc.html %}
|
||||
</ul>
|
||||
</nav>
|
|
@ -0,0 +1,83 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- 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/. -->
|
||||
<html lang="en-us">
|
||||
{% include head.html %}
|
||||
<body>
|
||||
|
||||
<div class="page-wrap">
|
||||
<div class="side-bar">
|
||||
<a href="{{ site.url }}{{ site.baseurl }}" class="site-title fs-6 lh-tight">
|
||||
<img src="{{ site.url }}{{ site.baseurl }}/assets/geckoview_icon_fullcolor-green.png" title="GeckoView" alt="GeckoView" style="vertical-align:middle; width:60px; height:60px">
|
||||
<span>GeckoView</span>
|
||||
</a>
|
||||
<span class="fs-3"><button class="js-main-nav-trigger navigation-list-toggle btn btn-outline" type="button" data-text-toggle="Hide">Menu</button></span>
|
||||
<div class="navigation main-nav js-main-nav">
|
||||
{% include nav.html %}
|
||||
</div>
|
||||
<footer role="contentinfo" class="site-footer">
|
||||
<p class="text-small text-grey-dk-000 mb-0">This site uses <a href="https://github.com/pmarsceill/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll.</p>
|
||||
</footer>
|
||||
</div>
|
||||
<div class="main-content-wrap">
|
||||
<div class="page-header">
|
||||
<div class="main-content">
|
||||
{% if site.search_enabled != nil %}
|
||||
<div class="search js-search">
|
||||
<div class="search-input-wrap">
|
||||
<input type="text" class="js-search-input search-input" tabindex="0" placeholder="Search {{ site.title }}" aria-label="Search {{ site.title }}" autocomplete="off">
|
||||
<svg width="14" height="14" viewBox="0 0 28 28" xmlns="http://www.w3.org/2000/svg" class="search-icon"><title>Search</title><g fill-rule="nonzero"><path d="M17.332 20.735c-5.537 0-10-4.6-10-10.247 0-5.646 4.463-10.247 10-10.247 5.536 0 10 4.601 10 10.247s-4.464 10.247-10 10.247zm0-4c3.3 0 6-2.783 6-6.247 0-3.463-2.7-6.247-6-6.247s-6 2.784-6 6.247c0 3.464 2.7 6.247 6 6.247z"/><path d="M11.672 13.791L.192 25.271 3.02 28.1 14.5 16.62z"/></g></svg>
|
||||
</div>
|
||||
<div class="js-search-results search-results-wrap"></div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if site.aux_links != nil %}
|
||||
<ul class="list-style-none text-small mt-md-1 mb-md-1 pb-4 pb-md-0 js-aux-nav aux-nav">
|
||||
{% for link in site.aux_links %}
|
||||
<li class="d-inline-block my-0{% unless forloop.last %} mr-2{% endunless %}"><a href="{{ link.last }}">{{ link.first }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="main-content js-main-content" tabindex="0">
|
||||
{% unless page.url == "/" %}
|
||||
{% if page.parent %}
|
||||
<nav class="breadcrumb-nav">
|
||||
<ol class="breadcrumb-nav-list">
|
||||
{% if page.grand_parent %}
|
||||
<li class="breadcrumb-nav-list-item"><a href="{{ first_level_url }}">{{ page.grand_parent }}</a></li>
|
||||
<li class="breadcrumb-nav-list-item"><a href="{{ second_level_url }}">{{ page.parent }}</a></li>
|
||||
{% else %}
|
||||
<li class="breadcrumb-nav-list-item"><a href="{{ first_level_url }}">{{ page.parent }}</a></li>
|
||||
{% endif %}
|
||||
<li class="breadcrumb-nav-list-item"><span>{{ page.title }}</span></li>
|
||||
</ol>
|
||||
</nav>
|
||||
{% endif %}
|
||||
{% endunless %}
|
||||
<div id="main-content" class="page-content" role="main">
|
||||
{{ content }}
|
||||
|
||||
{% if page.has_children == true and page.has_toc != false %}
|
||||
<hr>
|
||||
<h2 class="text-delta">Table of contents</h2>
|
||||
{% assign children_list = site.pages | sort:"nav_order" %}
|
||||
<ul>
|
||||
{% for child in children_list %}
|
||||
{% if child.parent == page.title and child.title != page.title %}
|
||||
<li>
|
||||
<a href="{{ child.url | absolute_url }}">{{ child.title }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,10 @@
|
|||
$sidebar-color: #ededf0;
|
||||
|
||||
$body-text-color: #4a4a4f;
|
||||
$body-heading-color: #2a2a2e;
|
||||
$nav-child-link-color: #2a2a2e;
|
||||
|
||||
$link-color: #0060df;
|
||||
$btn-primary-color: #003eaa;
|
||||
|
||||
$code-background-color: #ededf0;
|
|
@ -1,121 +0,0 @@
|
|||
.. -*- Mode: rst; fill-column: 80; -*-
|
||||
Configuring GeckoView for Automation
|
||||
####################################
|
||||
How to set environment variables, Gecko arguments, and Gecko preferences for automation and debugging.
|
||||
|
||||
.. contents:: :local:
|
||||
|
||||
Configuring GeckoView
|
||||
=====================================
|
||||
|
||||
GeckoView and the underlying Gecko engine have many, many options, switches, and toggles "under the hood". Automation (and to a lesser extent, debugging) can require configuring the Gecko engine to allow (or disallow) specific actions or features.
|
||||
|
||||
Some such actions and features are controlled by the `GeckoRuntimeSettings <../javadoc/mozilla-central/org/mozilla/geckoview/GeckoRuntimeSettings.html>`_ instance you configure in your consuming project. For example, remote debugging web content via the Firefox Developer Tools is configured by `GeckoRuntimeSettings.Builder#remoteDebuggingEnabled <../javadoc/mozilla-central/org/mozilla/geckoview/GeckoRuntimeSettings.Builder.html#remoteDebuggingEnabled-boolean-)>`_
|
||||
|
||||
Not all actions and features have GeckoView API interfaces. Generally, actions and features that do not have GeckoView API interfaces are not intended for broad usage. Configuration for these types of things is controlled by:
|
||||
|
||||
- environment variables in GeckoView's runtime environment
|
||||
- command line arguments to the Gecko process
|
||||
- internal Gecko preferences
|
||||
|
||||
Automation-specific configuration is generally in this category.
|
||||
|
||||
Running GeckoView with environment variables
|
||||
------------------------------------------------
|
||||
|
||||
After a successful ``./mach build``, ``./mach run --setenv`` can be used to run GeckoView with
|
||||
the given environment variables.
|
||||
|
||||
For example, to wait for attaching a debugger when starting a content tab process, use
|
||||
``./mach run --setenv MOZ_DEBUG_CHILD_WAIT_FOR_JAVA_DEBUGGER=:tab`` and then attach to that
|
||||
process within Android Studio.
|
||||
|
||||
Reading configuration from a file
|
||||
------------------------------------------------
|
||||
|
||||
When GeckoView is embedded into a debugabble application (i.e., when your manifest includes ``android:debuggable="true"``), by default GeckoView reads configuration from a file named ``/data/local/tmp/$PACKAGE-geckoview-config.yaml``. For example, if your Android package name is ``com.yourcompany.yourapp``, GeckoView will read configuration from::
|
||||
|
||||
/data/local/tmp/com.yourcompany.yourapp-geckoview-config.yaml
|
||||
|
||||
|
||||
Configuration file format
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The configuration file format is `YAML <https://yaml.org>`_. The following keys are recognized:
|
||||
|
||||
- ``env`` is a map from string environment variable name to string value to set in GeckoView's runtime environment
|
||||
- ``args`` is a list of string command line arguments to pass to the Gecko process
|
||||
- ``prefs`` is a map from string Gecko preference name to boolean, string, or integer value to set in the Gecko profile
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
# Contents of /data/local/tmp/com.yourcompany.yourapp-geckoview-config.yaml
|
||||
|
||||
env:
|
||||
MOZ_LOG: nsHttp:5
|
||||
|
||||
args:
|
||||
- --marionette
|
||||
- --profile
|
||||
- "/path/to/gecko-profile"
|
||||
|
||||
prefs:
|
||||
foo.bar.boolean: true
|
||||
foo.bar.string: "string"
|
||||
foo.bar.int: 500
|
||||
|
||||
|
||||
Verifying configuration from a file
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
When configuration from a file is read, GeckoView logs to ``adb logcat``, like: ::
|
||||
|
||||
GeckoRuntime I Adding debug configuration from: /data/local/tmp/org.mozilla.geckoview_example-geckoview-config.yaml
|
||||
GeckoDebugConfig D Adding environment variables from debug config: {MOZ_LOG=nsHttp:5}
|
||||
GeckoDebugConfig D Adding arguments from debug config: [--marionette]
|
||||
GeckoDebugConfig D Adding prefs from debug config: {foo.bar.baz=true}
|
||||
|
||||
|
||||
When a configuration file is found but cannot be parsed, an error is logged and the file is ignored entirely. When a configuration file is not found, nothing is logged.
|
||||
|
||||
Controlling configuration from a file
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
By default, GeckoView provides a secure web rendering engine. Custom configuration can compromise security in many ways: by storing sensitive data in insecure locations on the device, by trusting websites with incorrect security configurations, by not validating HTTP Public Key Pinning configurations; the list goes on.
|
||||
|
||||
**You should only allow such configuration if your end-user opts-in to the configuration!**
|
||||
|
||||
GeckoView will always read configuration from a file if the consuming Android package is set as the current Android "debug app" (see ``set-debug-app`` and ``clear-debug-app`` in the `adb documentation <https://developer.android.com/studio/command-line/adb>`_). An Android package can be set as the "debug app" without regard to the ``android:debuggable`` flag. There can only be one "debug app" set at a time. To disable the "debug app" check, `disable reading configuration from a file entirely <#disabling-reading-configuration-from-a-file-entirely>`_. Setting an Android package as the "debug app" requires privileged shell access to the device (generally via ``adb shell am ...``, which is only possible on devices which have ADB debugging enabled) and therefore it is safe to act on the "debug app" flag.
|
||||
|
||||
To enable reading configuration from a file: ::
|
||||
|
||||
adb shell am set-debug-app --persistent com.yourcompany.yourapp
|
||||
|
||||
|
||||
To disable reading configuration from a file: ::
|
||||
|
||||
adb shell am clear-debug-app
|
||||
|
||||
Enabling reading configuration from a file unconditionally
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Some applications (for example, web browsers) may want to allow configuration for automation unconditionally, i.e., even when the application is not debuggable, like release builds that have ``android:debuggable="false"``. In such cases, you can use `GeckoRuntimeSettings.Builder#configFilePath <javadoc/mozilla-central/org/mozilla/geckoview/GeckoRuntimeSettings.Builder.html#configFilePath-java.lang.String-)>`_ to force GeckoView to read configuration from the given file path, like:
|
||||
|
||||
.. code-block:: java
|
||||
|
||||
new GeckoRuntimeSettings.Builder()
|
||||
.configFilePath("/your/app/specific/location")
|
||||
.build();
|
||||
|
||||
Disabling reading configuration from a file entirely
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To force GeckoView to never read configuration from a file, even when the embedding application is debuggable, invoke `GeckoRuntimeSettings.Builder#configFilePath <javadoc/mozilla-central/org/mozilla/geckoview/GeckoRuntimeSettings.Builder.html#configFilePath-java.lang.String-)>`_ with an empty path, like:
|
||||
|
||||
.. code-block:: java
|
||||
|
||||
new GeckoRuntimeSettings.Builder()
|
||||
.configFilePath("")
|
||||
.build();
|
||||
|
||||
The empty path is recognized and no file I/O is performed.
|
|
@ -0,0 +1,121 @@
|
|||
---
|
||||
layout: default
|
||||
title: Configuring GeckoView for Automation
|
||||
summary: How to set environment variables, Gecko arguments, and Gecko preferences for automation and debugging.
|
||||
tags: [GeckoView,Gecko,mozilla,android,WebView,mobile,debugging,automation,config,configuration,environment,variables,arguments,preferences]
|
||||
nav_exclude: true
|
||||
exclude: true
|
||||
---
|
||||
## Table of contents
|
||||
{: .no_toc .text-delta }
|
||||
|
||||
1. TOC
|
||||
{:toc}
|
||||
|
||||
# Configuring GeckoView
|
||||
|
||||
GeckoView and the underlying Gecko engine have many, many options, switches, and toggles "under the hood". Automation (and to a lesser extent, debugging) can require configuring the Gecko engine to allow (or disallow) specific actions or features.
|
||||
|
||||
Some such actions and features are controlled by the [`GeckoRuntimeSettings`]({{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoRuntimeSettings.html) instance you configure in your consuming project. For example, remote debugging web content via the Firefox Developer Tools is configured by [`GeckoRuntimeSettings.Builder#remoteDebuggingEnabled`]({{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoRuntimeSettings.Builder.html#remoteDebuggingEnabled-boolean-)
|
||||
|
||||
Not all actions and features have GeckoView API interfaces. Generally, actions and features that do not have GeckoView API interfaces are not intended for broad usage. Configuration for these types of things is controlled by:
|
||||
- environment variables in GeckoView's runtime environment
|
||||
- command line arguments to the Gecko process
|
||||
- internal Gecko preferences
|
||||
|
||||
Automation-specific configuration is generally in this category.
|
||||
|
||||
## Running GeckoView with environment variables
|
||||
|
||||
After a successful `./mach build`, `./mach run --setenv` can be used to run GeckoView with
|
||||
the given environment variables.
|
||||
|
||||
For example, to wait for attaching a debugger when starting a content tab process, use
|
||||
`./mach run --setenv MOZ_DEBUG_CHILD_WAIT_FOR_JAVA_DEBUGGER=:tab` and then attach to that
|
||||
process within Android Studio.
|
||||
|
||||
## Reading configuration from a file
|
||||
|
||||
When GeckoView is embedded into a debugabble application (i.e., when your manifest includes `android:debuggable="true"`), by default GeckoView reads configuration from a file named `/data/local/tmp/$PACKAGE-geckoview-config.yaml`. For example, if your Android package name is `com.yourcompany.yourapp`, GeckoView will read configuration from
|
||||
```
|
||||
/data/local/tmp/com.yourcompany.yourapp-geckoview-config.yaml
|
||||
```
|
||||
|
||||
### Configuration file format
|
||||
|
||||
The configuration file format is [YAML](https://yaml.org). The following keys are recognized:
|
||||
- `env` is a map from string environment variable name to string value to set in GeckoView's runtime environment
|
||||
- `args` is a list of string command line arguments to pass to the Gecko process
|
||||
- `prefs` is a map from string Gecko preference name to boolean, string, or integer value to set in the Gecko profile
|
||||
|
||||
```yaml
|
||||
# Contents of /data/local/tmp/com.yourcompany.yourapp-geckoview-config.yaml
|
||||
|
||||
env:
|
||||
MOZ_LOG: nsHttp:5
|
||||
|
||||
args:
|
||||
- --marionette
|
||||
- --profile
|
||||
- "/path/to/gecko-profile"
|
||||
|
||||
prefs:
|
||||
foo.bar.boolean: true
|
||||
foo.bar.string: "string"
|
||||
foo.bar.int: 500
|
||||
```
|
||||
|
||||
### Verifying configuration from a file
|
||||
|
||||
When configuration from a file is read, GeckoView logs to `adb logcat`, like:
|
||||
|
||||
```
|
||||
GeckoRuntime I Adding debug configuration from: /data/local/tmp/org.mozilla.geckoview_example-geckoview-config.yaml
|
||||
GeckoDebugConfig D Adding environment variables from debug config: {MOZ_LOG=nsHttp:5}
|
||||
GeckoDebugConfig D Adding arguments from debug config: [--marionette]
|
||||
GeckoDebugConfig D Adding prefs from debug config: {foo.bar.baz=true}
|
||||
```
|
||||
|
||||
When a configuration file is found but cannot be parsed, an error is logged and the file is ignored entirely. When a configuration file is not found, nothing is logged.
|
||||
|
||||
### Controlling configuration from a file
|
||||
|
||||
By default, GeckoView provides a secure web rendering engine. Custom configuration can compromise security in many ways: by storing sensitive data in insecure locations on the device, by trusting websites with incorrect security configurations, by not validating HTTP Public Key Pinning configurations; the list goes on.
|
||||
|
||||
**You should only allow such configuration if your end-user opts-in to the configuration!**
|
||||
|
||||
GeckoView will always read configuration from a file if the consuming Android package is set as the current Android "debug app" (see `set-debug-app` and `clear-debug-app` in the [adb documentation](https://developer.android.com/studio/command-line/adb)). An Android package can be set as the "debug app" without regard to the `android:debuggable` flag. There can only be one "debug app" set at a time. To disable the "debug app" check, [disable reading configuration from a file entirely](#disabling-reading-configuration-from-a-file-entirely). Setting an Android package as the "debug app" requires privileged shell access to the device (generally via `adb shell am ...`, which is only possible on devices which have ADB debugging enabled) and therefore it is safe to act on the "debug app" flag.
|
||||
|
||||
To enable reading configuration from a file:
|
||||
|
||||
```
|
||||
adb shell am set-debug-app --persistent com.yourcompany.yourapp
|
||||
```
|
||||
|
||||
To disable reading configuration from a file:
|
||||
|
||||
```
|
||||
adb shell am clear-debug-app
|
||||
```
|
||||
|
||||
#### Enabling reading configuration from a file unconditionally
|
||||
|
||||
Some applications (for example, web browsers) may want to allow configuration for automation unconditionally, i.e., even when the application is not debuggable, like release builds that have `android:debuggable="false"`. In such cases, you can use [`GeckoRuntimeSettings.Builder#configFilePath`]({{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoRuntimeSettings.Builder.html#configFilePath-java.lang.String-) to force GeckoView to read configuration from the given file path, like:
|
||||
|
||||
```java
|
||||
new GeckoRuntimeSettings.Builder()
|
||||
.configFilePath("/your/app/specific/location")
|
||||
.build();
|
||||
```
|
||||
|
||||
#### Disabling reading configuration from a file entirely
|
||||
|
||||
To force GeckoView to never read configuration from a file, even when the embedding application is debuggable, invoke [`GeckoRuntimeSettings.Builder#configFilePath`]({{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoRuntimeSettings.Builder.html#configFilePath-java.lang.String-)` with an empty path, like:
|
||||
|
||||
```java
|
||||
new GeckoRuntimeSettings.Builder()
|
||||
.configFilePath("")
|
||||
.build();
|
||||
```
|
||||
|
||||
The empty path is recognized and no file I/O is performed.
|
|
@ -0,0 +1,100 @@
|
|||
---
|
||||
layout: default
|
||||
title: Getting Started with GeckoView
|
||||
nav_order: 2
|
||||
summary: How to use GeckoView in your Android app.
|
||||
tags: [GeckoView,Gecko,mozilla,android,WebView,mobile,mozilla-central,setup,quick start]
|
||||
---
|
||||
|
||||
_Building a browser? Check out [Android Components](https://mozilla-mobile.github.io/android-components/), our collection of ready-to-use support libraries!_
|
||||
|
||||
The following article is a brief guide to embedding GeckoView in an app. For a more in depth tutorial on getting started with GeckoView please read the article we have published on [raywenderlich.com](https://www.raywenderlich.com/1381698-android-tutorial-for-geckoview-getting-started).
|
||||
|
||||
## Table of contents
|
||||
{: .no_toc .text-delta }
|
||||
|
||||
1. TOC
|
||||
{:toc}
|
||||
|
||||
## Configure Gradle
|
||||
|
||||
You need to add or edit four stanzas inside your module's `build.gradle` file.
|
||||
|
||||
**1. Set the GeckoView version**
|
||||
|
||||
_Like Firefox, GeckoView has three release channels: Stable, Beta, and Nightly. Browse the [Maven Repository](https://maven.mozilla.org/?prefix=maven2/org/mozilla/geckoview/) to see currently available builds._
|
||||
|
||||
```groovy
|
||||
ext {
|
||||
geckoviewChannel = "nightly"
|
||||
geckoviewVersion = "70.0.20190712095934"
|
||||
}
|
||||
```
|
||||
|
||||
**2. Add Mozilla's Maven repository**
|
||||
```groovy
|
||||
repositories {
|
||||
maven {
|
||||
url "https://maven.mozilla.org/maven2/"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**3. Java 8 required support**
|
||||
|
||||
As GeckoView uses some Java 8 APIs, it requires these compatibility flags:
|
||||
|
||||
```groovy
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
```
|
||||
|
||||
**4. Add GeckoView Implementations**
|
||||
|
||||
```groovy
|
||||
dependencies {
|
||||
// ...
|
||||
implementation "org.mozilla.geckoview:geckoview-${geckoviewChannel}:${geckoviewVersion}"
|
||||
}
|
||||
```
|
||||
|
||||
## Add GeckoView to a Layout
|
||||
|
||||
Inside a layout `.xml` file, add the following:
|
||||
|
||||
```xml
|
||||
<org.mozilla.geckoview.GeckoView
|
||||
android:id="@+id/geckoview"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent" />
|
||||
```
|
||||
|
||||
## Initialize GeckoView in an Activity
|
||||
|
||||
**1. Import the GeckoView classes inside an Activity:**
|
||||
|
||||
```java
|
||||
import org.mozilla.geckoview.GeckoRuntime;
|
||||
import org.mozilla.geckoview.GeckoSession;
|
||||
import org.mozilla.geckoview.GeckoView;
|
||||
```
|
||||
|
||||
**2. In that activity's <code>onCreate</code> function, add the following:**
|
||||
|
||||
```java
|
||||
GeckoView view = findViewById(R.id.geckoview);
|
||||
GeckoSession session = new GeckoSession();
|
||||
GeckoRuntime runtime = GeckoRuntime.create(this);
|
||||
|
||||
session.open(runtime);
|
||||
view.setSession(session);
|
||||
session.loadUri("about:buildconfig"); // Or any other URL...
|
||||
```
|
||||
|
||||
## You're done!
|
||||
|
||||
Your application should now load and display a webpage inside of GeckoView.
|
||||
|
||||
To learn more about GeckoView's capabilities, review GeckoView's [JavaDoc](https://mozilla.github.io/geckoview/javadoc/mozilla-central/) or the [reference application](https://searchfox.org/mozilla-central/source/mobile/android/geckoview_example).
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
layout: default
|
||||
title: Using GeckoView
|
||||
nav_order: 3
|
||||
---
|
||||
|
||||
# Usage Documentation
|
||||
|
||||
We are working on providing detailed usage documentation for all of GeckoView's most popular features. Here is what we have so far.
|
||||
|
||||
- [GeckoView Quick Start Guide](geckoview-quick-start):
|
||||
Get GeckoView up and running inside your application.
|
||||
- [Interacting with Web Content](web-extensions):
|
||||
Writing Web Extensions, running content scripts and interacting with Javascript running in a web page.
|
||||
- [Working with Site Permissions](permissions):
|
||||
Handling and responding to requests from websites for permissions, such as geolocation, storage, media etc.
|
||||
- [Configuring GeckoView for Automation](automation):
|
||||
Get GeckoView set up on your automation system.
|
||||
|
||||
If there is documentation that you feel is missing, or an existing document doesn't cover the aspect that you are looking for, please request it by raising an issue on our [documentation site](https://github.com/mozilla/geckoview/issues).
|
|
@ -0,0 +1,289 @@
|
|||
---
|
||||
layout: default
|
||||
title: Working with Site Permissions
|
||||
summary: How to receive and respond to permission requests from websites.
|
||||
nav_exclude: true
|
||||
exclude: true
|
||||
tags: [GeckoView,Gecko,mozilla,android,WebView,mobile,permissions,site,media,grant,notifications,storage,persistent storage,app]
|
||||
---
|
||||
# Working with Site Permissions
|
||||
|
||||
When a website wants to access certain services on a user's device, it will send out a permissions request. This document will explain how to use GeckoView to receive those requests, and respond to them by granting or denying those permissions.
|
||||
|
||||
## The Permission Delegate
|
||||
|
||||
The way an app interacts with site permissions in GeckoView is through the [`PermissionDelegate`][1]. There are three broad categories of permission that the `PermissionDelegate` handles, Android Permissions, Content Permissions and Media Permissions. All site permissions handled by GeckoView fall into one of these three categories.
|
||||
|
||||
To get notified about permission requests, you need to implement the `PermissionDelegate` interface:
|
||||
|
||||
```java
|
||||
private class ExamplePermissionDelegate implements GeckoSession.PermissionDelegate {
|
||||
@Override
|
||||
public void onAndroidPermissionsRequest(final GeckoSession session,
|
||||
final String[] permissions,
|
||||
final Callback callback) { }
|
||||
|
||||
@Override
|
||||
public void onContentPermissionRequest(final GeckoSession session,
|
||||
final String uri,
|
||||
final int type, final Callback callback) { }
|
||||
|
||||
@Override
|
||||
public void onMediaPermissionRequest(final GeckoSession session,
|
||||
final String uri,
|
||||
final MediaSource[] video,
|
||||
final MediaSource[] audio,
|
||||
final MediaCallback callback) { }
|
||||
}
|
||||
```
|
||||
|
||||
You will then need to register the delegate with your [`GeckoSession`][3] instance.
|
||||
|
||||
```java
|
||||
public class GeckoViewActivity extends AppCompatActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
...
|
||||
|
||||
final ExamplePermissionDelegate permission = new ExamplePermissionDelegate();
|
||||
session.setPermissionDelegate(permission);
|
||||
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Android Permissions
|
||||
|
||||
Android permissions are requested whenever a site wants access to a device's navigation or input capabilities.
|
||||
|
||||
The user will often need to grant these Android permissions to the app alongside granting the Content or Media site permissions.
|
||||
|
||||
When you receive an [`onAndroidPermissionsRequest`][2] call, you will also receive the `GeckoSession` the request was sent from, an array containing the permissions that are being requested, and a [`Callback`][4] to respond to the request. It is then up to the app to request those permissions from the device, which can be done using [`requestPermissions`][5].
|
||||
|
||||
Possible `permissions` values are; [`ACCESS_COARSE_LOCATION`][6], [`ACCESS_FINE_LOCATION`][7], [`CAMERA`][8] or [`RECORD_AUDIO`][9].
|
||||
|
||||
```java
|
||||
private class ExamplePermissionDelegate implements GeckoSession.PermissionDelegate {
|
||||
private Callback mCallback;
|
||||
|
||||
public void onRequestPermissionsResult(final String[] permissions,
|
||||
final int[] grantResults) {
|
||||
if (mCallback == null) { return; }
|
||||
|
||||
final Callback cb = mCallback;
|
||||
mCallback = null;
|
||||
for (final int result : grantResults) {
|
||||
if (result != PackageManager.PERMISSION_GRANTED) {
|
||||
// At least one permission was not granted.
|
||||
cb.reject();
|
||||
return;
|
||||
}
|
||||
}
|
||||
cb.grant();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAndroidPermissionsRequest(final GeckoSession session,
|
||||
final String[] permissions,
|
||||
final Callback callback) {
|
||||
mCallback = callback;
|
||||
requestPermissions(permissions, androidPermissionRequestCode);
|
||||
}
|
||||
}
|
||||
|
||||
public class GeckoViewActivity extends AppCompatActivity {
|
||||
@Override
|
||||
public void onRequestPermissionsResult(final int requestCode,
|
||||
final String[] permissions,
|
||||
final int[] grantResults) {
|
||||
if (requestCode == REQUEST_PERMISSIONS ||
|
||||
requestCode == REQUEST_WRITE_EXTERNAL_STORAGE) {
|
||||
final ExamplePermissionDelegate permission = (ExamplePermissionDelegate)
|
||||
getCurrentSession().getPermissionDelegate();
|
||||
permission.onRequestPermissionsResult(permissions, grantResults);
|
||||
} else {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Content Permissions
|
||||
|
||||
Content permissions are requested whenever a site wants access to content that is stored on the device. The content permissions that can be requested through GeckoView are; [`Geolocation`][10], [`Site Notifications`][11] [`Persistent Storage`][12] and [`XR`][13] access.
|
||||
|
||||
When you receive an [`onContentPermissionRequest`][14] call, you will also receive the `GeckoSession` the request was sent from, the URI of the site that requested the permission, as a String, the type of the content permission requested (geolocation, site notification or persistent storage), and a [`Callback`][4] to respond to the request. It is then up to the app to present UI to the user asking for the permissions, and to notify GeckoView of the response via the `Callback`.
|
||||
|
||||
*Please note, in the case of `PERMISSION_DESKTOP_NOTIFICATION` and `PERMISSION_PERSISTENT_STORAGE`, GeckoView does not track accepted permissions and prevent further requests being sent for a particular site. It is therefore up to the calling app to do this if that is the desired behaviour. The code below demonstrates how to track storage permissions by site and track notification permission rejection for the whole app*
|
||||
|
||||
```java
|
||||
private class ExamplePermissionDelegate implements GeckoSession.PermissionDelegate {
|
||||
private boolean showNotificationsRejected;
|
||||
private ArrayList<String> acceptedPersistentStorage = new ArrayList<String>();
|
||||
|
||||
@Override
|
||||
public void onContentPermissionRequest(final GeckoSession session,
|
||||
final String uri,
|
||||
final int type,
|
||||
final Callback callback) {
|
||||
final int resId;
|
||||
Callback contentPermissionCallback = callback;
|
||||
if (PERMISSION_GEOLOCATION == type) {
|
||||
resId = R.string.request_geolocation;
|
||||
} else if (PERMISSION_DESKTOP_NOTIFICATION == type) {
|
||||
if (showNotificationsRejected) {
|
||||
callback.reject();
|
||||
return;
|
||||
}
|
||||
resId = R.string.request_notification;
|
||||
} else if (PERMISSION_PERSISTENT_STORAGE == type) {
|
||||
if (acceptedPersistentStorage.contains(uri)) {
|
||||
callback.grant();
|
||||
return;
|
||||
}
|
||||
resId = R.string.request_storage;
|
||||
} else if (PERMISSION_XR == type) {
|
||||
resId = R.string.request_xr;
|
||||
} else { // unknown permission type
|
||||
callback.reject();
|
||||
return;
|
||||
}
|
||||
|
||||
final String title = getString(resId, Uri.parse(uri).getAuthority());
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
builder.setTitle(title)
|
||||
.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final DialogInterface dialog, final int which) {
|
||||
if (PERMISSION_DESKTOP_NOTIFICATION == type) {
|
||||
showNotificationsRejected = false;
|
||||
}
|
||||
callback.reject();
|
||||
}
|
||||
})
|
||||
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final DialogInterface dialog, final int which) {
|
||||
if (PERMISSION_PERSISTENT_STORAGE == type) {
|
||||
acceptedPersistentStorage.add(mUri);
|
||||
} else if (PERMISSION_DESKTOP_NOTIFICATION == type) {
|
||||
showNotificationsRejected = true;
|
||||
}
|
||||
callback.grant();
|
||||
}
|
||||
});
|
||||
|
||||
final AlertDialog dialog = builder.create();
|
||||
dialog.show();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Media Permissions
|
||||
Media permissions are requested whenever a site wants access to play or record media from the device's camera and microphone.
|
||||
|
||||
When you receive an [`onMediaPermissionRequest`][15] call, you will also receive the `GeckoSession` the request was sent from, the URI of the site that requested the permission, as a String, the list of video devices available, if requesting video, the list of audio devices available, if requesting audio, and a [`MediaCallback`][17] to respond to the request.
|
||||
|
||||
It is up to the app to present UI to the user asking for the permissions, and to notify GeckoView of the response via the `MediaCallback`.
|
||||
|
||||
*Please note, media permissions will still be requested if the associated device permissions have been denied if there are video or audio sources in that category that can still be accessed when listed. It is the responsibility of consumers to ensure that media permission requests are not displayed in this case.*
|
||||
|
||||
```java
|
||||
private class ExamplePermissionDelegate implements GeckoSession.PermissionDelegate {
|
||||
@Override
|
||||
public void onMediaPermissionRequest(final GeckoSession session,
|
||||
final String uri,
|
||||
final MediaSource[] video,
|
||||
final MediaSource[] audio,
|
||||
final MediaCallback callback) {
|
||||
// Reject permission if Android permission has been previously denied.
|
||||
if ((audio != null
|
||||
&& ContextCompat.checkSelfPermission(GeckoViewActivity.this,
|
||||
Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED)
|
||||
|| (video != null
|
||||
&& ContextCompat.checkSelfPermission(GeckoViewActivity.this,
|
||||
Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)) {
|
||||
callback.reject();
|
||||
return;
|
||||
}
|
||||
|
||||
final String host = Uri.parse(uri).getAuthority();
|
||||
final String title;
|
||||
if (audio == null) {
|
||||
title = getString(R.string.request_video, host);
|
||||
} else if (video == null) {
|
||||
title = getString(R.string.request_audio, host);
|
||||
} else {
|
||||
title = getString(R.string.request_media, host);
|
||||
}
|
||||
|
||||
// Get the media device name from the `MediaDevice`
|
||||
String[] videoNames = normalizeMediaName(video);
|
||||
String[] audioNames = normalizeMediaName(audio);
|
||||
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
|
||||
// Create drop down boxes to allow users to select which device to grant permission to
|
||||
final LinearLayout container = addStandardLayout(builder, title, null);
|
||||
final Spinner videoSpinner;
|
||||
if (video != null) {
|
||||
videoSpinner = addMediaSpinner(builder.getContext(), container, video, videoNames); // create spinner and add to alert UI
|
||||
} else {
|
||||
videoSpinner = null;
|
||||
}
|
||||
|
||||
final Spinner audioSpinner;
|
||||
if (audio != null) {
|
||||
audioSpinner = addMediaSpinner(builder.getContext(), container, audio, audioNames); // create spinner and add to alert UI
|
||||
} else {
|
||||
audioSpinner = null;
|
||||
}
|
||||
|
||||
builder.setNegativeButton(android.R.string.cancel, null)
|
||||
.setPositiveButton(android.R.string.ok,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final DialogInterface dialog, final int which) {
|
||||
// gather selected media devices and grant access
|
||||
final MediaSource video = (videoSpinner != null)
|
||||
? (MediaSource) videoSpinner.getSelectedItem() : null;
|
||||
final MediaSource audio = (audioSpinner != null)
|
||||
? (MediaSource) audioSpinner.getSelectedItem() : null;
|
||||
callback.grant(video, audio);
|
||||
}
|
||||
});
|
||||
|
||||
final AlertDialog dialog = builder.create();
|
||||
dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
|
||||
@Override
|
||||
public void onDismiss(final DialogInterface dialog) {
|
||||
callback.reject();
|
||||
}
|
||||
});
|
||||
dialog.show();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To see the `PermissionsDelegate` in action, you can find the full example implementation in the [GeckoView example app][16].
|
||||
|
||||
[1]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html
|
||||
[2]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#onAndroidPermissionsRequest-org.mozilla.geckoview.GeckoSession-java.lang.String:A-org.mozilla.geckoview.GeckoSession.PermissionDelegate.Callback-
|
||||
[3]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.html
|
||||
[4]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.Callback.html
|
||||
[5]: https://developer.android.com/reference/android/app/Activity#requestPermissions(java.lang.String%5B%5D,%2520int)
|
||||
[6]: https://developer.android.com/reference/android/Manifest.permission.html#ACCESS_COARSE_LOCATION
|
||||
[7]: https://developer.android.com/reference/android/Manifest.permission.html#ACCESS_FINE_LOCATION
|
||||
[8]: https://developer.android.com/reference/android/Manifest.permission.html#CAMERA
|
||||
[9]: https://developer.android.com/reference/android/Manifest.permission.html#RECORD_AUDIO
|
||||
[10]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#PERMISSION_GEOLOCATION
|
||||
[11]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#PERMISSION_DESKTOP_NOTIFICATION
|
||||
[12]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#PERMISSION_PERSISTENT_STORAGE
|
||||
[13]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#PERMISSION_XR
|
||||
[14]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#onContentPermissionRequest-org.mozilla.geckoview.GeckoSession-java.lang.String-int-org.mozilla.geckoview.GeckoSession.PermissionDelegate.Callback-
|
||||
[15]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#onMediaPermissionRequest-org.mozilla.geckoview.GeckoSession-java.lang.String-org.mozilla.geckoview.GeckoSession.PermissionDelegate.MediaSource:A-org.mozilla.geckoview.GeckoSession.PermissionDelegate.MediaSource:A-org.mozilla.geckoview.GeckoSession.PermissionDelegate.MediaCallback-
|
||||
[16]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.MediaCallback.html
|
||||
[17]: https://searchfox.org/mozilla-central/source/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/GeckoViewActivity.java#686
|
|
@ -0,0 +1,391 @@
|
|||
---
|
||||
layout: default
|
||||
title: Interacting with Web content
|
||||
summary: How to interact with Web content and register WebExtensions in GeckoView.
|
||||
nav_exclude: true
|
||||
exclude: true
|
||||
---
|
||||
# Interacting with Web content and WebExtensions
|
||||
|
||||
GeckoView allows embedder applications to register and run [WebExtensions][8]
|
||||
in a GeckoView instance. Extensions are the preferred way to interact with
|
||||
Web content.
|
||||
|
||||
## Running extensions in GeckoView
|
||||
|
||||
Extensions bundled with applications can be provided in a folder in the
|
||||
`/assets` section of the APK. Like ordinary extensions, every extension bundled
|
||||
with GeckoView requires a [`manifest.json`][23] file.
|
||||
|
||||
To locate files bundled with the APK, GeckoView provides a shorthand
|
||||
`resource://android/` that points to the root of the APK.
|
||||
|
||||
E.g. `resource://android/assets/messaging/` will point to the
|
||||
`/assets/messaging/` folder present in the APK.
|
||||
|
||||
Note: Every installed extension will need an [`id`][25] and [`version`][26]
|
||||
specified in the `manifest.json` file.
|
||||
|
||||
To install a bundled extension in GeckoView, simply call
|
||||
[`WebExtensionController.installBuilt`][3].
|
||||
|
||||
```java
|
||||
runtime.getWebExtensionController()
|
||||
.installBuiltIn("resource://android/assets/messaging/")
|
||||
```
|
||||
|
||||
Note that the lifetime of the extension is not tied with the lifetime of the
|
||||
[`GeckoRuntime`][24] instance. The extension persist even when your app is
|
||||
restarted. Installing at every start up is fine, but it could be slow. To avoid
|
||||
installing multiple times you can query the list of installed extensions using
|
||||
`WebExtensionRuntime.list`:
|
||||
|
||||
```java
|
||||
runtime.getWebExtensionController().list().then(extensionList -> {
|
||||
for (WebExtension extension : extensionList) {
|
||||
if (extension.id.equals("messaging@example.com")
|
||||
&& extension.metaData.version.equals("1.0")) {
|
||||
// Extension already installed, no need to install it again
|
||||
return GeckoResult.fromValue(extension);
|
||||
}
|
||||
}
|
||||
|
||||
// Install if it's not already installed.
|
||||
return runtime.getWebExtensionController()
|
||||
.installBuiltIn("resource://android/assets/messaging/");
|
||||
}).accept(
|
||||
extension -> Log.i("MessageDelegate", "Extension installed: " + extension),
|
||||
e -> Log.e("MessageDelegate", "Error registering WebExtension", e)
|
||||
);
|
||||
```
|
||||
|
||||
## Communicating with Web Content
|
||||
GeckoView allows bidirectional communication with Web pages through
|
||||
extensions.
|
||||
|
||||
When using GeckoView, [native messaging][11] can be used for communicating to
|
||||
and from the browser.
|
||||
* [`runtime.sendNativeMessage`][12] for one-off messages.
|
||||
* [`runtime.connectNative`][13] for connection-based messaging.
|
||||
|
||||
Note: these APIs are only available when the `geckoViewAddons` [permission][17]
|
||||
is present in the `manifest.json` file of the extension.
|
||||
|
||||
### One-off messages
|
||||
|
||||
The easiest way to send messages from a [content script][9] or a [background
|
||||
script][10] is using [`runtime.sendNativeMessage`][12].
|
||||
|
||||
Note: Ordinarily, native extensions would use a [native manifest][27] to define
|
||||
what native app identifier to use. For GeckoView this is _not_ needed, the
|
||||
`nativeApp` parameter in `setMessageDelegate` will be use to determine what
|
||||
native app string is used.
|
||||
|
||||
### Messaging Example
|
||||
|
||||
To receive messages from the background script, call [`setMessageDelegate`][14]
|
||||
on the [`WebExtension`][3] object.
|
||||
|
||||
```java
|
||||
extension.setMessageDelegate(messageDelegate, "browser");
|
||||
```
|
||||
|
||||
[`SessionController.setMessageDelegate`][16] allows the app to
|
||||
receive messages from content scripts.
|
||||
|
||||
```java
|
||||
session.getWebExtensionController()
|
||||
.setMessageDelegate(extension, messageDelegate, "browser");
|
||||
```
|
||||
|
||||
Note: the `"browser"` parameter in the code above determines what native app id
|
||||
the extension can use to send native messages.
|
||||
|
||||
Note: extension can only send messages from content scripts if explicitly
|
||||
authorized by the app by adding `nativeMessagingFromContent` in the
|
||||
manifest.json file, e.g.
|
||||
|
||||
```json
|
||||
"permissions": [
|
||||
"nativeMessaging",
|
||||
"nativeMessagingFromContent",
|
||||
"geckoViewAddons"
|
||||
]
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
Let's set up an activity that registers an extension located in the
|
||||
`/assets/messaging/` folder of the APK. This activity will set up a
|
||||
[`MessageDelegate`][18] that will be used to communicate with Web Content.
|
||||
|
||||
You can find the full example here: [MessagingExample][20].
|
||||
|
||||
##### Activity.java
|
||||
```java
|
||||
WebExtension.MessageDelegate messageDelegate = new WebExtension.MessageDelegate() {
|
||||
@Nullable
|
||||
public GeckoResult<Object> onMessage(final @NonNull String nativeApp,
|
||||
final @NonNull Object message,
|
||||
final @NonNull WebExtension.MessageSender sender) {
|
||||
// The sender object contains information about the session that
|
||||
// originated this message and can be used to validate that the message
|
||||
// has been sent from the expected location.
|
||||
|
||||
// Be careful when handling the type of message as it depends on what
|
||||
// type of object was sent from the WebExtension script.
|
||||
if (message instanceof JSONObject) {
|
||||
// Do something with message
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// Let's check if the extension is already installed first
|
||||
runtime.getWebExtensionController().list().then(extensionList -> {
|
||||
for (WebExtension extension : extensionList) {
|
||||
if (extension.id.equals(EXTENSION_ID)
|
||||
&& extension.metaData.version.equals(EXTENSION_VERSION)) {
|
||||
// Extension already installed, no need to install it again
|
||||
return GeckoResult.fromValue(extension);
|
||||
}
|
||||
}
|
||||
|
||||
// Install if it's not already installed.
|
||||
return runtime.getWebExtensionController().installBuiltIn(EXTENSION_LOCATION);
|
||||
}).accept(
|
||||
// Set the delegate that will receive messages coming from this WebExtension.
|
||||
extension -> session.getWebExtensionController()
|
||||
.setMessageDelegate(extension, messageDelegate, "browser"),
|
||||
// Something bad happened, let's log an error
|
||||
e -> Log.e("MessageDelegate", "Error registering WebExtension", e)
|
||||
);
|
||||
```
|
||||
|
||||
Now add the `geckoViewAddons`, `nativeMessaging` and
|
||||
`nativeMessagingFromContent` permissions to your `manifest.json` file.
|
||||
|
||||
##### /assets/messaging/manifest.json
|
||||
```json
|
||||
{
|
||||
"manifest_version": 2,
|
||||
"name": "messaging",
|
||||
"version": "1.0",
|
||||
"description": "Example messaging web extension.",
|
||||
"browser_specific_settings": {
|
||||
"gecko": {
|
||||
"id": "messaging@example.com"
|
||||
}
|
||||
},
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": ["*://*.twitter.com/*"],
|
||||
"js": ["messaging.js"]
|
||||
}
|
||||
],
|
||||
"permissions": [
|
||||
"nativeMessaging",
|
||||
"nativeMessagingFromContent",
|
||||
"geckoViewAddons"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
And finally, write a content script that will send a message to the app when a
|
||||
certain event occurs. For example, you could send a message whenever a [WPA
|
||||
manifest][19] is found on the page. Note that our `nativeApp` identifier used
|
||||
for `sendNativeMessage` is the same as the one used in the `setMessageDelegate`
|
||||
call in [`Activity.java`](#activityjava).
|
||||
|
||||
##### /assets/messaging/messaging.js
|
||||
```javascript
|
||||
let manifest = document.querySelector("head > link[rel=manifest]");
|
||||
if (manifest) {
|
||||
fetch(manifest.href)
|
||||
.then(response => response.json())
|
||||
.then(json => {
|
||||
let message = {type: "WPAManifest", manifest: json};
|
||||
browser.runtime.sendNativeMessage("browser", message);
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
You can handle this message in the `onMessage` method in the `messageDelegate`
|
||||
[above](#activityjava).
|
||||
|
||||
```java
|
||||
@Nullable
|
||||
public GeckoResult<Object> onMessage(final @NonNull String nativeApp,
|
||||
final @NonNull Object message,
|
||||
final @NonNull WebExtension.MessageSender sender) {
|
||||
if (message instanceof JSONObject) {
|
||||
JSONObject json = (JSONObject) message;
|
||||
try {
|
||||
if (json.has("type") && "WPAManifest".equals(json.getString("type"))) {
|
||||
JSONObject manifest = json.getJSONObject("manifest");
|
||||
Log.d("MessageDelegate", "Found WPA manifest: " + manifest);
|
||||
}
|
||||
} catch (JSONException ex) {
|
||||
Log.e("MessageDelegate", "Invalid manifest", ex);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
```
|
||||
|
||||
Note that, in the case of content scripts, `sender.session` will be a reference
|
||||
to the `GeckoSession` instance from which the message originated. For
|
||||
background scripts, `sender.session` will always be `null`.
|
||||
|
||||
Also note that the type of `message` will depend on what was sent from the
|
||||
extension.
|
||||
|
||||
The type of `message` will be `JSONObject` when the extension sends a
|
||||
javascript object, but could also be a primitive type if the extension sends
|
||||
one, e.g. for
|
||||
|
||||
```javascript
|
||||
runtime.browser.sendNativeMessage("browser", "Hello World!");
|
||||
```
|
||||
|
||||
the type of `message` will be `java.util.String`.
|
||||
|
||||
## Connection-based messaging
|
||||
|
||||
For more complex scenarios or for when you want to send messages _from_ the app
|
||||
to the extension, [`runtime.connectNative`][13] is the appropriate API to
|
||||
use.
|
||||
|
||||
`connectNative` returns a [`runtime.Port`][6] that can be used to send messages
|
||||
to the app. On the app side, implementing [`MessageDelegate#onConnect`][1] will
|
||||
allow you to receive a [`Port`][7] object that can be used to receive and send
|
||||
messages to the extension.
|
||||
|
||||
The following example can be found [here][21].
|
||||
|
||||
For this example, the extension side will do the following:
|
||||
* open a port on the background script using `connectNative`
|
||||
* listen on the port and log to console every message received
|
||||
* send a message immediately after opening the port.
|
||||
|
||||
##### /assets/messaging/background.js
|
||||
```javascript
|
||||
// Establish connection with app
|
||||
let port = browser.runtime.connectNative("browser");
|
||||
port.onMessage.addListener(response => {
|
||||
// Let's just echo the message back
|
||||
port.postMessage(`Received: ${JSON.stringify(response)}`);
|
||||
});
|
||||
port.postMessage("Hello from WebExtension!");
|
||||
```
|
||||
|
||||
On the app side, following the [above](#activityjava) example, `onConnect` will
|
||||
be storing the `Port` object in a member variable and then using it when
|
||||
needed.
|
||||
|
||||
```java
|
||||
private WebExtension.Port mPort;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
// ... initialize GeckoView
|
||||
|
||||
// This delegate will handle all communications from and to a specific Port
|
||||
// object
|
||||
WebExtension.PortDelegate portDelegate = new WebExtension.PortDelegate() {
|
||||
public WebExtension.Port port = null;
|
||||
|
||||
public void onPortMessage(final @NonNull Object message,
|
||||
final @NonNull WebExtension.Port port) {
|
||||
// This method will be called every time a message is sent from the
|
||||
// extension through this port. For now, let's just log a
|
||||
// message.
|
||||
Log.d("PortDelegate", "Received message from WebExtension: "
|
||||
+ message);
|
||||
}
|
||||
|
||||
public void onDisconnect(final @NonNull WebExtension.Port port) {
|
||||
// After this method is called, this port is not usable anymore.
|
||||
if (port == mPort) {
|
||||
mPort = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// This delegate will handle requests to open a port coming from the
|
||||
// extension
|
||||
WebExtension.MessageDelegate messageDelegate = new WebExtension.MessageDelegate() {
|
||||
@Nullable
|
||||
public void onConnect(final @NonNull WebExtension.Port port) {
|
||||
// Let's store the Port object in a member variable so it can be
|
||||
// used later to exchange messages with the WebExtension.
|
||||
mPort = port;
|
||||
|
||||
// Registering the delegate will allow us to receive messages sent
|
||||
// through this port.
|
||||
mPort.setDelegate(portDelegate);
|
||||
}
|
||||
};
|
||||
|
||||
runtime.getWebExtensionController()
|
||||
.installBuiltIn("resource://android/assets/messaging/")
|
||||
.accept(
|
||||
// Register message delegate for background script
|
||||
extension -> extension.setMessageDelegate(messageDelegate, "browser"),
|
||||
e -> Log.e("MessageDelegate", "Error registering WebExtension", e)
|
||||
);
|
||||
|
||||
// ... other
|
||||
}
|
||||
```
|
||||
|
||||
For example, let's send a message to the extension every time the user long
|
||||
presses on a key on the virtual keyboard, e.g. on the back button.
|
||||
|
||||
```java
|
||||
@Override
|
||||
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
|
||||
if (mPort == null) {
|
||||
// No extension registered yet, let's ignore this message
|
||||
return false;
|
||||
}
|
||||
|
||||
JSONObject message = new JSONObject();
|
||||
try {
|
||||
message.put("keyCode", keyCode);
|
||||
message.put("event", KeyEvent.keyCodeToString(event.getKeyCode()));
|
||||
} catch (JSONException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
|
||||
mPort.postMessage(message);
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
This allows bidirectional communication between the app and the extension.
|
||||
|
||||
[1]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.MessageDelegate.html#onConnect-org.mozilla.geckoview.WebExtension.Port-
|
||||
[3]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.html
|
||||
[6]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/Port
|
||||
[7]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.Port.html
|
||||
[8]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions
|
||||
[9]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts
|
||||
[10]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Anatomy_of_a_WebExtension#Background_scripts
|
||||
[11]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging#Exchanging_messages
|
||||
[12]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/sendNativeMessage
|
||||
[13]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/connectNative
|
||||
[14]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.html#setMessageDelegate-org.mozilla.geckoview.WebExtension.MessageDelegate-java.lang.String-
|
||||
[15]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.html#WebExtension-java.lang.String-java.lang.String-long-
|
||||
[16]: ../javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.html#setMessageDelegate-org.mozilla.geckoview.WebExtension.MessageDelegate-java.lang.String-
|
||||
[17]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions
|
||||
[18]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.MessageDelegate.html
|
||||
[19]: https://developer.mozilla.org/en-US/docs/Web/Manifest
|
||||
[20]: https://searchfox.org/mozilla-central/source/mobile/android/examples/extensions/messaging_example/
|
||||
[21]: https://searchfox.org/mozilla-central/source/mobile/android/examples/extensions/port_messaging_example/
|
||||
[22]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.Flags.html#ALLOW_CONTENT_MESSAGING
|
||||
[23]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json
|
||||
[24]: {{ site.url }}{{ site.baseurl }}/javadoc/mozilla-central/org/mozilla/geckoview/GeckoRuntime.html
|
||||
[25]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/browser_specific_settings
|
||||
[26]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/version
|
||||
[27]: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging#App_manifest
|
|
@ -1,101 +0,0 @@
|
|||
.. -*- Mode: rst; fill-column: 80; -*-
|
||||
Getting Started with GeckoView
|
||||
######################################
|
||||
|
||||
How to use GeckoView in your Android app.
|
||||
|
||||
*Building a browser? Check out* `Android Components <https://mozilla-mobile.github.io/android-components/>`_, *our collection of ready-to-use support libraries!*
|
||||
|
||||
The following article is a brief guide to embedding GeckoView in an app. For a more in depth tutorial on getting started with GeckoView please read the article we have published on `raywenderlich.com <https://www.raywenderlich.com/1381698-android-tutorial-for-geckoview-getting-started>`_.
|
||||
|
||||
.. contents:: :local:
|
||||
|
||||
Configure Gradle
|
||||
=================
|
||||
|
||||
You need to add or edit four stanzas inside your module's ``build.gradle`` file.
|
||||
|
||||
**1. Set the GeckoView version**
|
||||
|
||||
*Like Firefox, GeckoView has three release channels: Stable, Beta, and Nightly. Browse the* `Maven Repository <https://maven.mozilla.org/?prefix=maven2/org/mozilla/geckoview/>`_ *to see currently available builds.*
|
||||
|
||||
.. code-block:: groovy
|
||||
|
||||
ext {
|
||||
geckoviewChannel = "nightly"
|
||||
geckoviewVersion = "70.0.20190712095934"
|
||||
}
|
||||
|
||||
|
||||
**2. Add Mozilla's Maven repository**
|
||||
|
||||
.. code-block:: groovy
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
url "https://maven.mozilla.org/maven2/"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
**3. Java 8 required support**
|
||||
|
||||
As GeckoView uses some Java 8 APIs, it requires these compatibility flags:
|
||||
|
||||
.. code-block:: groovy
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
**4. Add GeckoView Implementations**
|
||||
|
||||
.. code-block:: groovy
|
||||
|
||||
dependencies {
|
||||
// ...
|
||||
implementation "org.mozilla.geckoview:geckoview-${geckoviewChannel}:${geckoviewVersion}"
|
||||
}
|
||||
|
||||
Add GeckoView to a Layout
|
||||
==========================
|
||||
|
||||
Inside a layout ``.xml`` file, add the following:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<org.mozilla.geckoview.GeckoView
|
||||
android:id="@+id/geckoview"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent" />
|
||||
|
||||
Initialize GeckoView in an Activity
|
||||
====================================
|
||||
|
||||
**1. Import the GeckoView classes inside an Activity:**
|
||||
|
||||
.. code-block:: java
|
||||
|
||||
import org.mozilla.geckoview.GeckoRuntime;
|
||||
import org.mozilla.geckoview.GeckoSession;
|
||||
import org.mozilla.geckoview.GeckoView;
|
||||
|
||||
**2. In that activity's** ``onCreate`` **function, add the following:**
|
||||
|
||||
.. code-block:: java
|
||||
|
||||
GeckoView view = findViewById(R.id.geckoview);
|
||||
GeckoSession session = new GeckoSession();
|
||||
GeckoRuntime runtime = GeckoRuntime.create(this);
|
||||
|
||||
session.open(runtime);
|
||||
view.setSession(session);
|
||||
session.loadUri("about:buildconfig"); // Or any other URL...
|
||||
|
||||
You're done!
|
||||
==============
|
||||
|
||||
Your application should now load and display a webpage inside of GeckoView.
|
||||
|
||||
To learn more about GeckoView's capabilities, review GeckoView's `JavaDoc <javadoc/mozilla-central/>`_ or the `reference application <https://searchfox.org/mozilla-central/source/mobile/android/geckoview_example>`_.
|
|
@ -1,35 +0,0 @@
|
|||
.. -*- Mode: rst; fill-column: 80; -*-
|
||||
===============
|
||||
Using GeckoView
|
||||
===============
|
||||
|
||||
Usage Documentation
|
||||
===================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:hidden:
|
||||
|
||||
geckoview-quick-start
|
||||
web-extensions
|
||||
permissions
|
||||
automation
|
||||
|
||||
We are working on providing detailed usage documentation for all of
|
||||
GeckoView’s most popular features. Here is what we have so far.
|
||||
|
||||
- `GeckoView Quick Start Guide <geckoview-quick-start.html>`__: Get
|
||||
GeckoView up and running inside your application.
|
||||
- `Interacting with Web Content <web-extensions.html>`__: Writing Web
|
||||
Extensions, running content scripts and interacting with Javascript
|
||||
running in a web page.
|
||||
- `Working with Site Permissions <permissions.html>`__: Handling and
|
||||
responding to requests from websites for permissions, such as
|
||||
geolocation, storage, media etc.
|
||||
- `Configuring GeckoView for Automation <automation.html>`__: Get GeckoView
|
||||
set up on your automation system.
|
||||
|
||||
If there is documentation that you feel is missing, or an existing
|
||||
document doesn’t cover the aspect that you are looking for, please
|
||||
request it by raising an issue on our `documentation
|
||||
site <https://github.com/mozilla/geckoview/issues>`__.
|
|
@ -1,353 +0,0 @@
|
|||
.. -*- Mode: rst; fill-column: 80; -*-
|
||||
=============================
|
||||
Working with Site Permissions
|
||||
=============================
|
||||
|
||||
Working with Site Permissions
|
||||
=============================
|
||||
|
||||
When a website wants to access certain services on a user’s device, it
|
||||
will send out a permissions request. This document will explain how to
|
||||
use GeckoView to receive those requests, and respond to them by granting
|
||||
or denying those permissions.
|
||||
|
||||
.. contents:: :local:
|
||||
|
||||
The Permission Delegate
|
||||
-----------------------
|
||||
|
||||
The way an app interacts with site permissions in GeckoView is through
|
||||
the
|
||||
`PermissionDelegate <../javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html>`_.
|
||||
There are three broad categories of permission that the
|
||||
``PermissionDelegate`` handles, Android Permissions, Content Permissions
|
||||
and Media Permissions. All site permissions handled by GeckoView fall
|
||||
into one of these three categories.
|
||||
|
||||
To get notified about permission requests, you need to implement the
|
||||
``PermissionDelegate`` interface:
|
||||
|
||||
.. code:: java
|
||||
|
||||
private class ExamplePermissionDelegate implements GeckoSession.PermissionDelegate {
|
||||
@Override
|
||||
public void onAndroidPermissionsRequest(final GeckoSession session,
|
||||
final String[] permissions,
|
||||
final Callback callback) { }
|
||||
|
||||
@Override
|
||||
public void onContentPermissionRequest(final GeckoSession session,
|
||||
final String uri,
|
||||
final int type, final Callback callback) { }
|
||||
|
||||
@Override
|
||||
public void onMediaPermissionRequest(final GeckoSession session,
|
||||
final String uri,
|
||||
final MediaSource[] video,
|
||||
final MediaSource[] audio,
|
||||
final MediaCallback callback) { }
|
||||
}
|
||||
|
||||
You will then need to register the delegate with your
|
||||
`GeckoSession <../javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.html>`_
|
||||
instance.
|
||||
|
||||
.. code:: java
|
||||
|
||||
public class GeckoViewActivity extends AppCompatActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
...
|
||||
|
||||
final ExamplePermissionDelegate permission = new ExamplePermissionDelegate();
|
||||
session.setPermissionDelegate(permission);
|
||||
|
||||
...
|
||||
}
|
||||
}
|
||||
|
||||
Android Permissions
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Android permissions are requested whenever a site wants access to a
|
||||
device’s navigation or input capabilities.
|
||||
|
||||
The user will often need to grant these Android permissions to the app
|
||||
alongside granting the Content or Media site permissions.
|
||||
|
||||
When you receive an
|
||||
`onAndroidPermissionsRequest <../javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#onAndroidPermissionsRequest-org.mozilla.geckoview.GeckoSession-java.lang.String:A-org.mozilla.geckoview.GeckoSession.PermissionDelegate.Callback->`_
|
||||
call, you will also receive the ``GeckoSession`` the request was sent
|
||||
from, an array containing the permissions that are being requested, and
|
||||
a
|
||||
`Callback <../javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.Callback.html>`_
|
||||
to respond to the request. It is then up to the app to request those
|
||||
permissions from the device, which can be done using
|
||||
`requestPermissions <https://developer.android.com/reference/android/app/Activity#requestPermissions(java.lang.String%5B%5D,%2520int)>`_.
|
||||
|
||||
Possible ``permissions`` values are;
|
||||
|
||||
`ACCESS_COARSE_LOCATION <https://developer.android.com/reference/android/Manifest.permission.html#ACCESS_COARSE_LOCATION>`_,
|
||||
|
||||
`ACCESS_FINE_LOCATION <https://developer.android.com/reference/android/Manifest.permission.html#ACCESS_FINE_LOCATION>`_,
|
||||
|
||||
`CAMERA <https://developer.android.com/reference/android/Manifest.permission.html#CAMERA>`_
|
||||
|
||||
or
|
||||
|
||||
`RECORD_AUDIO <https://developer.android.com/reference/android/Manifest.permission.html#RECORD_AUDIO>`_.
|
||||
|
||||
.. code:: java
|
||||
|
||||
private class ExamplePermissionDelegate implements GeckoSession.PermissionDelegate {
|
||||
private Callback mCallback;
|
||||
|
||||
public void onRequestPermissionsResult(final String[] permissions,
|
||||
final int[] grantResults) {
|
||||
if (mCallback == null) { return; }
|
||||
|
||||
final Callback cb = mCallback;
|
||||
mCallback = null;
|
||||
for (final int result : grantResults) {
|
||||
if (result != PackageManager.PERMISSION_GRANTED) {
|
||||
// At least one permission was not granted.
|
||||
cb.reject();
|
||||
return;
|
||||
}
|
||||
}
|
||||
cb.grant();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAndroidPermissionsRequest(final GeckoSession session,
|
||||
final String[] permissions,
|
||||
final Callback callback) {
|
||||
mCallback = callback;
|
||||
requestPermissions(permissions, androidPermissionRequestCode);
|
||||
}
|
||||
}
|
||||
|
||||
public class GeckoViewActivity extends AppCompatActivity {
|
||||
@Override
|
||||
public void onRequestPermissionsResult(final int requestCode,
|
||||
final String[] permissions,
|
||||
final int[] grantResults) {
|
||||
if (requestCode == REQUEST_PERMISSIONS ||
|
||||
requestCode == REQUEST_WRITE_EXTERNAL_STORAGE) {
|
||||
final ExamplePermissionDelegate permission = (ExamplePermissionDelegate)
|
||||
getCurrentSession().getPermissionDelegate();
|
||||
permission.onRequestPermissionsResult(permissions, grantResults);
|
||||
} else {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Content Permissions
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Content permissions are requested whenever a site wants access to
|
||||
content that is stored on the device. The content permissions that can
|
||||
be requested through GeckoView are;
|
||||
|
||||
`Geolocation <../javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#PERMISSION_GEOLOCATION>`_,
|
||||
|
||||
`Site Notifications <../javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#PERMISSION_DESKTOP_NOTIFICATION>`_
|
||||
|
||||
`Persistent Storage <../javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#PERMISSION_PERSISTENT_STORAGE>`_
|
||||
|
||||
and
|
||||
|
||||
`XR <../javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#PERMISSION_XR>`_
|
||||
|
||||
access.
|
||||
|
||||
When you receive an
|
||||
`onContentPermissionRequest <../javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#onContentPermissionRequest-org.mozilla.geckoview.GeckoSession-java.lang.String-int-org.mozilla.geckoview.GeckoSession.PermissionDelegate.Callback->`_
|
||||
call, you will also receive the ``GeckoSession`` the request was sent
|
||||
from, the URI of the site that requested the permission, as a String,
|
||||
the type of the content permission requested (geolocation, site
|
||||
notification or persistent storage), and a
|
||||
`Callback <../javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.Callback.html>`_
|
||||
to respond to the request. It is then up to the app to present UI to the
|
||||
user asking for the permissions, and to notify GeckoView of the response
|
||||
via the ``Callback``.
|
||||
|
||||
*Please note, in the case of ``PERMISSION_DESKTOP_NOTIFICATION`` and
|
||||
``PERMISSION_PERSISTENT_STORAGE``, GeckoView does not track accepted
|
||||
permissions and prevent further requests being sent for a particular
|
||||
site. It is therefore up to the calling app to do this if that is the
|
||||
desired behaviour. The code below demonstrates how to track storage
|
||||
permissions by site and track notification permission rejection for the
|
||||
whole app*
|
||||
|
||||
.. code:: java
|
||||
|
||||
private class ExamplePermissionDelegate implements GeckoSession.PermissionDelegate {
|
||||
private boolean showNotificationsRejected;
|
||||
private ArrayList<String> acceptedPersistentStorage = new ArrayList<String>();
|
||||
|
||||
@Override
|
||||
public void onContentPermissionRequest(final GeckoSession session,
|
||||
final String uri,
|
||||
final int type,
|
||||
final Callback callback) {
|
||||
final int resId;
|
||||
Callback contentPermissionCallback = callback;
|
||||
if (PERMISSION_GEOLOCATION == type) {
|
||||
resId = R.string.request_geolocation;
|
||||
} else if (PERMISSION_DESKTOP_NOTIFICATION == type) {
|
||||
if (showNotificationsRejected) {
|
||||
callback.reject();
|
||||
return;
|
||||
}
|
||||
resId = R.string.request_notification;
|
||||
} else if (PERMISSION_PERSISTENT_STORAGE == type) {
|
||||
if (acceptedPersistentStorage.contains(uri)) {
|
||||
callback.grant();
|
||||
return;
|
||||
}
|
||||
resId = R.string.request_storage;
|
||||
} else if (PERMISSION_XR == type) {
|
||||
resId = R.string.request_xr;
|
||||
} else { // unknown permission type
|
||||
callback.reject();
|
||||
return;
|
||||
}
|
||||
|
||||
final String title = getString(resId, Uri.parse(uri).getAuthority());
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
builder.setTitle(title)
|
||||
.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final DialogInterface dialog, final int which) {
|
||||
if (PERMISSION_DESKTOP_NOTIFICATION == type) {
|
||||
showNotificationsRejected = false;
|
||||
}
|
||||
callback.reject();
|
||||
}
|
||||
})
|
||||
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final DialogInterface dialog, final int which) {
|
||||
if (PERMISSION_PERSISTENT_STORAGE == type) {
|
||||
acceptedPersistentStorage.add(mUri);
|
||||
} else if (PERMISSION_DESKTOP_NOTIFICATION == type) {
|
||||
showNotificationsRejected = true;
|
||||
}
|
||||
callback.grant();
|
||||
}
|
||||
});
|
||||
|
||||
final AlertDialog dialog = builder.create();
|
||||
dialog.show();
|
||||
}
|
||||
}
|
||||
|
||||
Media Permissions
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
Media permissions are requested whenever a site wants access to play or
|
||||
record media from the device’s camera and microphone.
|
||||
|
||||
When you receive an
|
||||
`onMediaPermissionRequest <%7B%7B%20site.url%20%7D%7D%7B%7B%20site.baseurl%20%7D%7D/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.html#onMediaPermissionRequest-org.mozilla.geckoview.GeckoSession-java.lang.String-org.mozilla.geckoview.GeckoSession.PermissionDelegate.MediaSource:A-org.mozilla.geckoview.GeckoSession.PermissionDelegate.MediaSource:A-org.mozilla.geckoview.GeckoSession.PermissionDelegate.MediaCallback->`_
|
||||
call, you will also receive the ``GeckoSession`` the request was sent
|
||||
from, the URI of the site that requested the permission, as a String,
|
||||
the list of video devices available, if requesting video, the list of
|
||||
audio devices available, if requesting audio, and a
|
||||
`MediaCallback <https://searchfox.org/mozilla-central/source/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/GeckoViewActivity.java#686>`_
|
||||
to respond to the request.
|
||||
|
||||
It is up to the app to present UI to the user asking for the
|
||||
permissions, and to notify GeckoView of the response via the
|
||||
``MediaCallback``.
|
||||
|
||||
*Please note, media permissions will still be requested if the
|
||||
associated device permissions have been denied if there are video or
|
||||
audio sources in that category that can still be accessed when listed.
|
||||
It is the responsibility of consumers to ensure that media permission
|
||||
requests are not displayed in this case.*
|
||||
|
||||
.. code:: java
|
||||
|
||||
private class ExamplePermissionDelegate implements GeckoSession.PermissionDelegate {
|
||||
@Override
|
||||
public void onMediaPermissionRequest(final GeckoSession session,
|
||||
final String uri,
|
||||
final MediaSource[] video,
|
||||
final MediaSource[] audio,
|
||||
final MediaCallback callback) {
|
||||
// Reject permission if Android permission has been previously denied.
|
||||
if ((audio != null
|
||||
&& ContextCompat.checkSelfPermission(GeckoViewActivity.this,
|
||||
Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED)
|
||||
|| (video != null
|
||||
&& ContextCompat.checkSelfPermission(GeckoViewActivity.this,
|
||||
Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED)) {
|
||||
callback.reject();
|
||||
return;
|
||||
}
|
||||
|
||||
final String host = Uri.parse(uri).getAuthority();
|
||||
final String title;
|
||||
if (audio == null) {
|
||||
title = getString(R.string.request_video, host);
|
||||
} else if (video == null) {
|
||||
title = getString(R.string.request_audio, host);
|
||||
} else {
|
||||
title = getString(R.string.request_media, host);
|
||||
}
|
||||
|
||||
// Get the media device name from the `MediaDevice`
|
||||
String[] videoNames = normalizeMediaName(video);
|
||||
String[] audioNames = normalizeMediaName(audio);
|
||||
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
|
||||
// Create drop down boxes to allow users to select which device to grant permission to
|
||||
final LinearLayout container = addStandardLayout(builder, title, null);
|
||||
final Spinner videoSpinner;
|
||||
if (video != null) {
|
||||
videoSpinner = addMediaSpinner(builder.getContext(), container, video, videoNames); // create spinner and add to alert UI
|
||||
} else {
|
||||
videoSpinner = null;
|
||||
}
|
||||
|
||||
final Spinner audioSpinner;
|
||||
if (audio != null) {
|
||||
audioSpinner = addMediaSpinner(builder.getContext(), container, audio, audioNames); // create spinner and add to alert UI
|
||||
} else {
|
||||
audioSpinner = null;
|
||||
}
|
||||
|
||||
builder.setNegativeButton(android.R.string.cancel, null)
|
||||
.setPositiveButton(android.R.string.ok,
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final DialogInterface dialog, final int which) {
|
||||
// gather selected media devices and grant access
|
||||
final MediaSource video = (videoSpinner != null)
|
||||
? (MediaSource) videoSpinner.getSelectedItem() : null;
|
||||
final MediaSource audio = (audioSpinner != null)
|
||||
? (MediaSource) audioSpinner.getSelectedItem() : null;
|
||||
callback.grant(video, audio);
|
||||
}
|
||||
});
|
||||
|
||||
final AlertDialog dialog = builder.create();
|
||||
dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
|
||||
@Override
|
||||
public void onDismiss(final DialogInterface dialog) {
|
||||
callback.reject();
|
||||
}
|
||||
});
|
||||
dialog.show();
|
||||
}
|
||||
}
|
||||
|
||||
To see the ``PermissionsDelegate`` in action, you can find the full
|
||||
example implementation in the `GeckoView example
|
||||
app <%7B%7B%20site.url%20%7D%7D%7B%7B%20site.baseurl%20%7D%7D/javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.PermissionDelegate.MediaCallback.html>`_.
|
|
@ -1,360 +0,0 @@
|
|||
.. -*- Mode: rst; fill-column: 80; -*-
|
||||
============================
|
||||
Interacting with Web content
|
||||
============================
|
||||
|
||||
Interacting with Web content and WebExtensions
|
||||
==============================================
|
||||
|
||||
GeckoView allows embedder applications to register and run
|
||||
`WebExtensions <https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions>`_
|
||||
in a GeckoView instance. WebExtensions are the preferred way to interact
|
||||
with Web content.
|
||||
|
||||
.. contents:: :local:
|
||||
|
||||
Running WebExtensions in GeckoView
|
||||
----------------------------------
|
||||
|
||||
WebExtensions bundled with applications can be provided either in
|
||||
compressed ``.xpi`` files or in regular folders. Like ordinary
|
||||
WebExtensions, every WebExtension requires a
|
||||
`manifest.json <https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json>`_
|
||||
file.
|
||||
|
||||
To run a WebExtension in GeckoView, simply create a
|
||||
`WebExtension <%7B%7B%20site.url%20%7D%7D%7B%7B%20site.baseurl%20%7D%7D/javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.html>`_
|
||||
object and register it in your
|
||||
`GeckoRuntime <%7B%7B%20site.url%20%7D%7D%7B%7B%20site.baseurl%20%7D%7D/javadoc/mozilla-central/org/mozilla/geckoview/GeckoRuntime.html>`_
|
||||
instance.
|
||||
|
||||
.. code:: java
|
||||
|
||||
WebExtension extension = new WebExtension(
|
||||
// The location where the web extension is installed, if the location is a
|
||||
// folder make sure the path ends with a "/" character.
|
||||
"resource://android/assets/messaging/",
|
||||
// This is the id and must be unique for every web extension
|
||||
"myextension@example.com",
|
||||
// Extra flags can be specified here
|
||||
WebExtension.Flags.NONE);
|
||||
|
||||
// Run the WebExtension
|
||||
runtime.registerWebExtension(extension);
|
||||
|
||||
Note that the lifetime of the WebExtension is tied with the lifetime of
|
||||
the
|
||||
`GeckoRuntime <%7B%7B%20site.url%20%7D%7D%7B%7B%20site.baseurl%20%7D%7D/javadoc/mozilla-central/org/mozilla/geckoview/GeckoRuntime.html>`_
|
||||
instance. The WebExtension will need to be registered every time the
|
||||
runtime is created and will not persist once the runtime is closed.
|
||||
|
||||
To locate files bundled with the APK, GeckoView provides a shorthand
|
||||
``resource://android/`` that points to the root of the APK.
|
||||
|
||||
E.g. ``resource://android/assets/messaging/`` will point to the
|
||||
``/assets/messaging/`` folder present in the APK.
|
||||
|
||||
Communicating with Web Content
|
||||
------------------------------
|
||||
|
||||
GeckoView allows bidirectional communication with Web pages through
|
||||
WebExtensions.
|
||||
|
||||
When using GeckoView, `native
|
||||
messaging <https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging#Exchanging_messages>`_
|
||||
can be used for communicating to and from the browser.
|
||||
|
||||
- `runtime.sendNativeMessage <https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/sendNativeMessage>`_
|
||||
for one-off messages.
|
||||
- `runtime.connectNative <https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/connectNative>`_
|
||||
for connection-based messaging.
|
||||
|
||||
Note: these APIs are only available when the ``geckoViewAddons``
|
||||
`permission <https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions>`_
|
||||
is present in the ``manifest.json`` file of the WebExtension.
|
||||
|
||||
One-off messages
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
The easiest way to send messages from a `content
|
||||
script <https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts>`_
|
||||
or a `background
|
||||
script <https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Anatomy_of_a_WebExtension#Background_scripts>`_
|
||||
is using
|
||||
`runtime.sendNativeMessage <https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/sendNativeMessage>`_.
|
||||
The app will set up a message delegate on the same ``nativeApp`` that
|
||||
the WebExtension is using to send messages. In our example we will use
|
||||
the ``"browser"`` native app identifier.
|
||||
|
||||
To receive messages from the background script, call
|
||||
`setMessageDelegate <%7B%7B%20site.url%20%7D%7D%7B%7B%20site.baseurl%20%7D%7D/javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.html#setMessageDelegate-org.mozilla.geckoview.WebExtension.MessageDelegate-java.lang.String->`_
|
||||
on the
|
||||
`WebExtension <%7B%7B%20site.url%20%7D%7D%7B%7B%20site.baseurl%20%7D%7D/javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.html>`_
|
||||
object.
|
||||
|
||||
`GeckoSession.setMessageDelegate <../javadoc/mozilla-central/org/mozilla/geckoview/GeckoSession.html#setMessageDelegate-org.mozilla.geckoview.WebExtension.MessageDelegate-java.lang.String->`_
|
||||
allows the app to receive messages from content scripts.
|
||||
|
||||
Note: WebExtensions can only send messages from content scripts if
|
||||
explicitly authorized by the app setting
|
||||
`WebExtension.Flags.ALLOW_CONTENT_MESSAGING <%7B%7B%20site.url%20%7D%7D%7B%7B%20site.baseurl%20%7D%7D/javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.Flags.html#ALLOW_CONTENT_MESSAGING>`_
|
||||
in the
|
||||
`constructor <%7B%7B%20site.url%20%7D%7D%7B%7B%20site.baseurl%20%7D%7D/javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.html#WebExtension-java.lang.String-java.lang.String-long->`_.
|
||||
|
||||
Example
|
||||
~~~~~~~
|
||||
|
||||
Let’s set up an activity that registers a WebExtension located in the
|
||||
``/assets/messaging/`` folder of the APK. This activity will set up a
|
||||
`MessageDelegate <%7B%7B%20site.url%20%7D%7D%7B%7B%20site.baseurl%20%7D%7D/javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.MessageDelegate.html>`_
|
||||
that will be used to communicate with Web Content.
|
||||
|
||||
You can find the full example here:
|
||||
`MessagingExample <https://searchfox.org/mozilla-central/source/mobile/android/examples/extensions/messaging_example/>`_.
|
||||
|
||||
Activity.java
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
.. code:: java
|
||||
|
||||
WebExtension.MessageDelegate messageDelegate = new WebExtension.MessageDelegate() {
|
||||
@Nullable
|
||||
public GeckoResult<Object> onMessage(final @NonNull Object message,
|
||||
final @NonNull WebExtension.MessageSender sender) {
|
||||
// The sender object contains information about the session that
|
||||
// originated this message and can be used to validate that the message
|
||||
// has been sent from the expected location.
|
||||
|
||||
// Be careful when handling the type of message as it depends on what
|
||||
// type of object was sent from the WebExtension script.
|
||||
if (message instanceof JSONObject) {
|
||||
// Do something with message
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
WebExtension extension = new WebExtension(
|
||||
"resource://android/assets/messaging/",
|
||||
"myextension@example.com",
|
||||
WebExtension.Flags.ALLOW_CONTENT_MESSAGING);
|
||||
|
||||
// Run the WebExtension
|
||||
runtime.registerWebExtension(extension);
|
||||
|
||||
// Set the delegate that will receive messages coming from this WebExtension.
|
||||
session.setMessageDelegate(messageDelegate, "browser");
|
||||
|
||||
Now add the ``geckoViewAddons`` and ``nativeMessaging`` permissions to
|
||||
your ``manifest.json`` file.
|
||||
|
||||
/assets/messaging/manifest.json
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code:: json
|
||||
|
||||
{
|
||||
"manifest_version": 2,
|
||||
"name": "messaging",
|
||||
"version": "1.0",
|
||||
"description": "Example messaging web extension.",
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": ["*://*.twitter.com/*"],
|
||||
"js": ["messaging.js"]
|
||||
}
|
||||
],
|
||||
"permissions": [
|
||||
"nativeMessaging",
|
||||
"geckoViewAddons"
|
||||
]
|
||||
}
|
||||
|
||||
And finally, write a content script that will send a message to the app
|
||||
when a certain event occurs. For example, you could send a message
|
||||
whenever a `WPA
|
||||
manifest <https://developer.mozilla.org/en-US/docs/Web/Manifest>`_ is
|
||||
found on the page. Note that our ``nativeApp`` identifier used for
|
||||
``sendNativeMessage`` is the same as the one used in the
|
||||
``setMessageDelegate`` call in `Activity.java <#activityjava>`_.
|
||||
|
||||
/assets/messaging/messaging.js
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code:: javascript
|
||||
|
||||
let manifest = document.querySelector("head > link[rel=manifest]");
|
||||
if (manifest) {
|
||||
fetch(manifest.href)
|
||||
.then(response => response.json())
|
||||
.then(json => {
|
||||
let message = {type: "WPAManifest", manifest: json};
|
||||
browser.runtime.sendNativeMessage("browser", message);
|
||||
});
|
||||
}
|
||||
|
||||
You can handle this message in the ``onMessage`` method in the
|
||||
``messageDelegate`` `above <#activityjava>`_.
|
||||
|
||||
.. code:: java
|
||||
|
||||
@Nullable
|
||||
public GeckoResult<Object> onMessage(final @NonNull Object message,
|
||||
final @NonNull WebExtension.MessageSender sender) {
|
||||
if (message instanceof JSONObject) {
|
||||
JSONObject json = (JSONObject) message;
|
||||
try {
|
||||
if (json.has("type") && "WPAManifest".equals(json.getString("type"))) {
|
||||
JSONObject manifest = json.getJSONObject("manifest");
|
||||
Log.d("MessageDelegate", "Found WPA manifest: " + manifest);
|
||||
}
|
||||
} catch (JSONException ex) {
|
||||
Log.e("MessageDelegate", "Invalid manifest", ex);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Note that, in the case of content scripts, ``sender.session`` will be a
|
||||
reference to the ``GeckoSession`` instance from which the message
|
||||
originated. For background scripts, ``sender.session`` will always be
|
||||
``null``.
|
||||
|
||||
Also note that the type of ``message`` will depend on what was sent from
|
||||
the WebExtension.
|
||||
|
||||
The type of ``message`` will be ``JSONObject`` when the WebExtension
|
||||
sends a javascript object, but could also be a primitive type if the
|
||||
WebExtension sends one, e.g. for
|
||||
|
||||
.. code:: javascript
|
||||
|
||||
runtime.browser.sendNativeMessage("browser", "Hello World!");
|
||||
|
||||
the type of ``message`` will be ``java.util.String``.
|
||||
|
||||
Connection-based messaging
|
||||
--------------------------
|
||||
|
||||
For more complex scenarios or for when you want to send messages *from*
|
||||
the app to the WebExtension,
|
||||
`runtime.connectNative <https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/connectNative>`_
|
||||
is the appropriate API to use.
|
||||
|
||||
``connectNative`` returns a
|
||||
`runtime.Port <https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/Port>`_
|
||||
that can be used to send messages to the app. On the app side,
|
||||
implementing
|
||||
`MessageDelegate#onConnect <../javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.MessageDelegate.html#onConnect-org.mozilla.geckoview.WebExtension.Port->`_
|
||||
will allow you to receive a
|
||||
`Port <../javadoc/mozilla-central/org/mozilla/geckoview/WebExtension.Port.html>`_
|
||||
object that can be used to receive and send messages to the
|
||||
WebExtension.
|
||||
|
||||
The following example can be found
|
||||
`here <https://searchfox.org/mozilla-central/source/mobile/android/examples/extensions/port_messaging_example/>`_.
|
||||
|
||||
For this example, the WebExtension side will do the following:
|
||||
|
||||
- open a port on the background script using ``connectNative``
|
||||
- listen on the port and log to console every message received
|
||||
- send a message immediately after opening the port.
|
||||
|
||||
/assets/messaging/background.js
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code:: javascript
|
||||
|
||||
// Establish connection with app
|
||||
let port = browser.runtime.connectNative("browser");
|
||||
port.onMessage.addListener(response => {
|
||||
// Let's just echo the message back
|
||||
port.postMessage(`Received: ${JSON.stringify(response)}`);
|
||||
});
|
||||
port.postMessage("Hello from WebExtension!");
|
||||
|
||||
On the app side, following the `above <#activityjava>`_ example,
|
||||
``onConnect`` will be storing the ``Port`` object in a member variable
|
||||
and then using it when needed.
|
||||
|
||||
.. code:: java
|
||||
|
||||
private WebExtension.Port mPort;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
// ... initialize GeckoView
|
||||
|
||||
// This delegate will handle all communications from and to a specific Port
|
||||
// object
|
||||
WebExtension.PortDelegate portDelegate = new WebExtension.PortDelegate() {
|
||||
public WebExtension.Port port = null;
|
||||
|
||||
public void onPortMessage(final @NonNull Object message,
|
||||
final @NonNull WebExtension.Port port) {
|
||||
// This method will be called every time a message is sent from the
|
||||
// WebExtension through this port. For now, let's just log a
|
||||
// message.
|
||||
Log.d("PortDelegate", "Received message from WebExtension: "
|
||||
+ message);
|
||||
}
|
||||
|
||||
public void onDisconnect(final @NonNull WebExtension.Port port) {
|
||||
// After this method is called, this port is not usable anymore.
|
||||
if (port == mPort) {
|
||||
mPort = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// This delegate will handle requests to open a port coming from the
|
||||
// WebExtension
|
||||
WebExtension.MessageDelegate messageDelegate = new WebExtension.MessageDelegate() {
|
||||
@Nullable
|
||||
public void onConnect(final @NonNull WebExtension.Port port) {
|
||||
// Let's store the Port object in a member variable so it can be
|
||||
// used later to exchange messages with the WebExtension.
|
||||
mPort = port;
|
||||
|
||||
// Registering the delegate will allow us to receive messages sent
|
||||
// through this port.
|
||||
mPort.setDelegate(portDelegate);
|
||||
}
|
||||
};
|
||||
|
||||
WebExtension extension = new WebExtension(
|
||||
"resource://android/assets/messaging/");
|
||||
|
||||
// Register message delegate for the background script
|
||||
extension.setMessageDelegate(messageDelegate, "browser");
|
||||
|
||||
// ... other
|
||||
}
|
||||
|
||||
For example, let’s send a message to the WebExtension every time the
|
||||
user long presses on a key on the virtual keyboard, e.g. on the back
|
||||
button.
|
||||
|
||||
.. code:: java
|
||||
|
||||
@Override
|
||||
public boolean onKeyLongPress(int keyCode, KeyEvent event) {
|
||||
if (mPort == null) {
|
||||
// No WebExtension registered yet, let's ignore this message
|
||||
return false;
|
||||
}
|
||||
|
||||
JSONObject message = new JSONObject();
|
||||
try {
|
||||
message.put("keyCode", keyCode);
|
||||
message.put("event", KeyEvent.keyCodeToString(event.getKeyCode()));
|
||||
} catch (JSONException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
|
||||
mPort.postMessage(message);
|
||||
return true;
|
||||
}
|
||||
|
||||
This allows bidirectional communication between the app and the
|
||||
WebExtension.
|
|
@ -0,0 +1,142 @@
|
|||
---
|
||||
layout: default
|
||||
title: Mozilla Central Contributor Guide
|
||||
summary: Guide to setting up as a contributor to mozilla-central.
|
||||
tags: [GeckoView,Gecko,mozilla,android,WebView,mobile,mozilla-central,bug fix,submit,patch,arcanist,arc,moz-phab,phabricator]
|
||||
nav_exclude: true
|
||||
exclude: true
|
||||
---
|
||||
## Table of contents
|
||||
{: .no_toc .text-delta }
|
||||
|
||||
1. TOC
|
||||
{:toc}
|
||||
|
||||
# Submitting a patch to Firefox using Git.
|
||||
|
||||
This guide will take you through submitting and updating a patch to `mozilla-central` as a git user. You need to already be [set up to use git to contribute to `mozilla-central`](mc-quick-start).
|
||||
|
||||
## Performing a bug fix
|
||||
|
||||
All of the open bugs for issues in Firefox can be found in [Bugzilla](https://bugzilla.mozilla.org). If you know the component that you wish to contribute to you can use Bugzilla to search for issues in that project. If you are unsure which component you are interested in, you can search the [Good First Bugs](https://bugzilla.mozilla.org/buglist.cgi?quicksearch=good-first-bug) list to find something you want to work on.
|
||||
|
||||
* Once you have your bug, assign it to yourself in Bugzilla.
|
||||
* Update your local copy of the firefox codebase to match the current version on the servers to ensure you are working with the most up to date code.
|
||||
|
||||
```bash
|
||||
git remote update
|
||||
```
|
||||
* Create a new feature branch tracking either Central or Inbound.
|
||||
|
||||
```bash
|
||||
git checkout -b bugxxxxxxx [inbound|central]/default
|
||||
```
|
||||
* Work on your bug, checking into git according to your preferred workflow. _Try to ensure that each individual commit compiles and passes all of the tests for your component. This will make it easier to land if you use `moz-phab` to submit (details later in this post)._
|
||||
|
||||
It may be helpful to have Mozilla commit access, at least level 1. There are three levels of commit access that give increasing levels of access to the repositories.
|
||||
|
||||
Level 1: Try/User access. You will need this level of access commit to the try server.
|
||||
Level 2: General access. This will give you full commit access to any mercurial or SVN repository not requiring level 3 access.
|
||||
Level 3: Core access. You will need this level to commit directly to any of the core repositories (Firefox/Thunderbird/Fennec).
|
||||
|
||||
If you wish to apply for commit access, please follow the guide found in the [Mozilla Commit Access Policy](https://www.mozilla.org/en-US/about/governance/policies/commit/access-policy/).
|
||||
|
||||
### Submitting a patch that touches C/C++
|
||||
|
||||
If your patch makes changes to any C or C++ code and your editor does not have `clang-format` support, you should run the clang-format linter before submitting your patch to ensure that your code is properly formatted.
|
||||
|
||||
```bash
|
||||
mach clang-format -p path/to/file.cpp
|
||||
```
|
||||
|
||||
Note that `./mach bootstrap` will offer to set up a commit hook that will automatically do this for you.
|
||||
|
||||
### Submitting to `try` with Level 1 commit access.
|
||||
|
||||
If you only have Level 1 access, you will still need to submit your patch through phabricator, but you can test it on the try server first.
|
||||
|
||||
* Use `./mach try fuzzy` to select jobs to run and push to try.
|
||||
|
||||
### Submitting a patch via Phabricator.
|
||||
|
||||
To commit anything to the repository, you will need to set up Arcanist and Phabricator. If you are using `git-cinnabar` then you will need to use git enabled versions of these tools.
|
||||
|
||||
#### Install Arcanist (Github version)
|
||||
|
||||
* Ensure PHP is installed
|
||||
* [Install Arcanist](https://secure.phabricator.com/book/phabricator/article/arcanist_quick_start/)
|
||||
|
||||
#### Set up Phabricator
|
||||
|
||||
* In a browser, visit Mozilla's Phabricator instance at https://phabricator.services.mozilla.com/.
|
||||
* Click "Log In" at the top of the page
|
||||
|
||||
![alt text]({{ site.url }}/assets/LogInPhab.png "Log in to Phabricator")
|
||||
* Click the "Log In or Register" button on the next page. This will take you to Bugzilla to log in or register a new account.
|
||||
|
||||
![alt text]({{ site.url }}/assets/LogInOrRegister.png "Log in or register a Phabiricator account")
|
||||
* Sign in with your Bugzilla credentials, or create a new account.
|
||||
|
||||
![alt text]({{ site.url }}/assets/LogInBugzilla.png "Log in with Bugzilla")
|
||||
* You will be redirected back to Phabricator, where you will have to create a new Phabricator account.
|
||||
<Screenshot Needed>
|
||||
* Fill in/amend any fields on the form and click "Register Account".
|
||||
<Screenshot Needed>
|
||||
* You now have a Phabricator account and can submit and review patches.
|
||||
|
||||
#### Using Arcanist to submit a patch
|
||||
|
||||
* Ensure you are on the branch where you have commits that you want to submit.
|
||||
|
||||
```bash
|
||||
git checkout "your-branch-with-commits"
|
||||
```
|
||||
* Create a differential patch containing your commits
|
||||
|
||||
```bash
|
||||
arc diff
|
||||
```
|
||||
|
||||
* If you have any uncommitted files, Arcanist will ask if you want to commit them.
|
||||
* If you have any files in the path not added to git Arcanist will ask if you want to ignore them.
|
||||
* After formatting your patch, Arcanist will open a nano/emacs file for you to enter the commit details. If you have many individual git commits in your arcanist diff then the first line of the first commit message will become the patch title, and the rest of the commit, plus the messages for the other commits in the patch will form the summary.
|
||||
* Ensure you have entered the bug number against the `Bug #` field.
|
||||
* If you know who you want to review your patch, put their Phabricator handle against the `reviewers` field. If in doubt, look to see who filed, or is listed as a mentor on, the bug you are addressing and choose them.
|
||||
* Close the editor (Ctrl X) to save the patch.
|
||||
* Arcanist now formats your patch and submits it to Phabricator. It will display the Phabricator link in the output.
|
||||
* Copy that link and paste it into a browser window to view your patch.
|
||||
|
||||
You may have noticed when using Arcanist that it wraps all of your carefully curated Github commits into a single patch. If you have made many commits that are self contained and pass all the tests then you may wish to submit a patch for each commit. This will make it easier to review. The way to do this is via `moz-phab`. `moz-phab` required Arcanist so you do have to have that installed first.
|
||||
|
||||
#### Installing `moz-phab`
|
||||
|
||||
```bash
|
||||
pip install MozPhab [--user]
|
||||
```
|
||||
|
||||
#### Submitting a patch using `moz-phab`.
|
||||
|
||||
* Ensure you are on the branch where you have commits that you want to submit.
|
||||
|
||||
```bash
|
||||
git checkout your-branch
|
||||
```
|
||||
* Check the revision numbers for the commits you want to submit
|
||||
|
||||
```bash
|
||||
git log
|
||||
```
|
||||
* Run `moz-phab`. Specifying a start commit will submit all commits from that commit. Specifying an end commit will submit all commits up to that commit. If no positional arguments are provided, the range is determined to be starting with the first non-public, non-obsolete changeset (for Mercurial) and ending with the currently checked-out changeset.
|
||||
|
||||
```bash
|
||||
moz-phab submit [start_rev] [end_rev]
|
||||
```
|
||||
* You will receive a Phabricator link for each commit in the set.
|
||||
|
||||
### Updating a patch
|
||||
|
||||
* Often you will need to make amendments to a patch after it has been submitted to address review comments. To do this, add your commits to the base branch of your fix as normal.
|
||||
|
||||
To submit the update using Arcanist, run `arc diff --update <PhabricatorDifferentialNumber>`.
|
||||
|
||||
For `moz-phab` run in the same way as the initial submission with the same arguments, that is, specifying the full original range of commits. Note that, while inserting and amending commits should work fine, reordering commits is not yet supported, and deleting commits will leave the associated revisions open, which should be abandoned manually
|
|
@ -1,239 +0,0 @@
|
|||
=================================
|
||||
Mozilla Central Contributor Guide
|
||||
=================================
|
||||
|
||||
Table of contents
|
||||
=================
|
||||
|
||||
.. contents:: :local:
|
||||
|
||||
Submitting a patch to Firefox using Git.
|
||||
========================================
|
||||
|
||||
This guide will take you through submitting and updating a patch to
|
||||
``mozilla-central`` as a git user. You need to already be `set up to use
|
||||
git to contribute to mozilla-central <mc-quick-start.html>`_.
|
||||
|
||||
Performing a bug fix
|
||||
--------------------
|
||||
|
||||
All of the open bugs for issues in Firefox can be found in
|
||||
`Bugzilla <https://bugzilla.mozilla.org>`_. If you know the component
|
||||
that you wish to contribute to you can use Bugzilla to search for issues
|
||||
in that project. If you are unsure which component you are interested
|
||||
in, you can search the `Good First
|
||||
Bugs <https://bugzilla.mozilla.org/buglist.cgi?quicksearch=good-first-bug>`_
|
||||
list to find something you want to work on.
|
||||
|
||||
- Once you have your bug, assign it to yourself in Bugzilla.
|
||||
- Update your local copy of the firefox codebase to match the current
|
||||
version on the servers to ensure you are working with the most up to
|
||||
date code.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
git remote update
|
||||
|
||||
- Create a new feature branch tracking either Central or Inbound.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
git checkout -b bugxxxxxxx [inbound|central]/default
|
||||
|
||||
- Work on your bug, checking into git according to your preferred
|
||||
workflow. *Try to ensure that each individual commit compiles and
|
||||
passes all of the tests for your component. This will make it easier
|
||||
to land if you use ``moz-phab`` to submit (details later in this
|
||||
post).*
|
||||
|
||||
It may be helpful to have Mozilla commit access, at least level 1. There
|
||||
are three levels of commit access that give increasing levels of access
|
||||
to the repositories.
|
||||
|
||||
Level 1: Try/User access. You will need this level of access commit to
|
||||
the try server.
|
||||
|
||||
Level 2: General access. This will give you full commit
|
||||
access to any mercurial or SVN repository not requiring level 3 access.
|
||||
|
||||
Level 3: Core access. You will need this level to commit directly to any
|
||||
of the core repositories (Firefox/Thunderbird/Fennec).
|
||||
|
||||
If you wish to apply for commit access, please follow the guide found in
|
||||
the `Mozilla Commit Access
|
||||
Policy <https://www.mozilla.org/en-US/about/governance/policies/commit/access-policy/>`_.
|
||||
|
||||
Submitting a patch that touches C/C++
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If your patch makes changes to any C or C++ code and your editor does
|
||||
not have ``clang-format`` support, you should run the clang-format
|
||||
linter before submitting your patch to ensure that your code is properly
|
||||
formatted.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
mach clang-format -p path/to/file.cpp
|
||||
|
||||
Note that ``./mach bootstrap`` will offer to set up a commit hook that
|
||||
will automatically do this for you.
|
||||
|
||||
Submitting to ``try`` with Level 1 commit access.
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you only have Level 1 access, you will still need to submit your
|
||||
patch through phabricator, but you can test it on the try server first.
|
||||
|
||||
- Use ``./mach try fuzzy`` to select jobs to run and push to try.
|
||||
|
||||
Submitting a patch via Phabricator.
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To commit anything to the repository, you will need to set up Arcanist
|
||||
and Phabricator. If you are using ``git-cinnabar`` then you will need to
|
||||
use git enabled versions of these tools.
|
||||
|
||||
Install Arcanist (Github version)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Ensure PHP is installed
|
||||
- `Install
|
||||
Arcanist <https://secure.phabricator.com/book/phabricator/article/arcanist_quick_start/>`_
|
||||
|
||||
Set up Phabricator
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- In a browser, visit Mozilla’s Phabricator instance at
|
||||
https://phabricator.services.mozilla.com/.
|
||||
|
||||
- Click “Log In” at the top of the page
|
||||
|
||||
.. figure:: ../assets/LogInPhab.png
|
||||
:alt: Log in to Phabricator
|
||||
|
||||
alt text
|
||||
|
||||
- Click the “Log In or Register” button on the next page. This will
|
||||
take you to Bugzilla to log in or register a new account.
|
||||
|
||||
.. figure:: ../assets/LogInOrRegister.png
|
||||
:alt: Log in or register a Phabiricator account
|
||||
|
||||
alt text
|
||||
|
||||
- Sign in with your Bugzilla credentials, or create a new account.
|
||||
|
||||
.. figure:: ../assets/LogInBugzilla.png
|
||||
:alt: Log in with Bugzilla
|
||||
|
||||
alt text
|
||||
|
||||
- You will be redirected back to Phabricator, where you will have to
|
||||
create a new Phabricator account.
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<Screenshot Needed>
|
||||
|
||||
- Fill in/amend any fields on the form and click “Register Account”.
|
||||
|
||||
.. raw:: html
|
||||
|
||||
<Screenshot Needed>
|
||||
|
||||
- You now have a Phabricator account and can submit and review patches.
|
||||
|
||||
Using Arcanist to submit a patch
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Ensure you are on the branch where you have commits that you want to
|
||||
submit.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
git checkout "your-branch-with-commits"
|
||||
|
||||
- Create a differential patch containing your commits
|
||||
|
||||
.. code:: bash
|
||||
|
||||
arc diff
|
||||
|
||||
- If you have any uncommitted files, Arcanist will ask if you want to
|
||||
commit them.
|
||||
- If you have any files in the path not added to git Arcanist will ask
|
||||
if you want to ignore them.
|
||||
- After formatting your patch, Arcanist will open a nano/emacs file for
|
||||
you to enter the commit details. If you have many individual git
|
||||
commits in your arcanist diff then the first line of the first commit
|
||||
message will become the patch title, and the rest of the commit, plus
|
||||
the messages for the other commits in the patch will form the
|
||||
summary.
|
||||
- Ensure you have entered the bug number against the ``Bug #`` field.
|
||||
- If you know who you want to review your patch, put their Phabricator
|
||||
handle against the ``reviewers`` field. If in doubt, look to see who
|
||||
filed, or is listed as a mentor on, the bug you are addressing and
|
||||
choose them.
|
||||
- Close the editor (Ctrl X) to save the patch.
|
||||
- Arcanist now formats your patch and submits it to Phabricator. It
|
||||
will display the Phabricator link in the output.
|
||||
- Copy that link and paste it into a browser window to view your patch.
|
||||
|
||||
You may have noticed when using Arcanist that it wraps all of your
|
||||
carefully curated Github commits into a single patch. If you have made
|
||||
many commits that are self contained and pass all the tests then you may
|
||||
wish to submit a patch for each commit. This will make it easier to
|
||||
review. The way to do this is via ``moz-phab``. ``moz-phab`` required
|
||||
Arcanist so you do have to have that installed first.
|
||||
|
||||
Installing ``moz-phab``
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code:: bash
|
||||
|
||||
pip install MozPhab [--user]
|
||||
|
||||
Submitting a patch using ``moz-phab``.
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- Ensure you are on the branch where you have commits that you want to
|
||||
submit.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
git checkout your-branch
|
||||
|
||||
- Check the revision numbers for the commits you want to submit
|
||||
|
||||
.. code:: bash
|
||||
|
||||
git log
|
||||
|
||||
- Run ``moz-phab``. Specifying a start commit will submit all commits
|
||||
from that commit. Specifying an end commit will submit all commits up
|
||||
to that commit. If no positional arguments are provided, the range is
|
||||
determined to be starting with the first non-public, non-obsolete
|
||||
changeset (for Mercurial) and ending with the currently checked-out
|
||||
changeset.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
moz-phab submit [start_rev] [end_rev]
|
||||
|
||||
- You will receive a Phabricator link for each commit in the set.
|
||||
|
||||
Updating a patch
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
- Often you will need to make amendments to a patch after it has been
|
||||
submitted to address review comments. To do this, add your commits to
|
||||
the base branch of your fix as normal.
|
||||
|
||||
To submit the update using Arcanist, run
|
||||
``arc diff --update <PhabricatorDifferentialNumber>``.
|
||||
|
||||
For ``moz-phab`` run in the same way as the initial submission with the
|
||||
same arguments, that is, specifying the full original range of commits.
|
||||
Note that, while inserting and amending commits should work fine,
|
||||
reordering commits is not yet supported, and deleting commits will leave
|
||||
the associated revisions open, which should be abandoned manually
|
|
@ -0,0 +1,70 @@
|
|||
---
|
||||
layout: default
|
||||
title: GeckoView For Gecko Engineers
|
||||
summary: Guide to contributing to GeckoView for Gecko Engineers
|
||||
tags: [GeckoView,Gecko,mozilla,android,WebView,mobile,mozilla-central,setup,get started,compile,build,deploy,bug fix,submit,patch,arcanist,arc,moz-phab,phabricator]
|
||||
nav_exclude: true
|
||||
exclude: true
|
||||
---
|
||||
## Table of contents
|
||||
{: .no_toc .text-delta }
|
||||
|
||||
1. TOC
|
||||
{:toc}
|
||||
|
||||
# GeckoView for Gecko Engineers
|
||||
|
||||
## Introduction
|
||||
Who this guide is for: As the title suggests, the target audience of this guide is existing Gecko engineers who need to be able to build and (locally) test GeckoView. If you aren’t already familiar with building Firefox on a desktop platform, you’ll likely be better served by reading [our general introduction](geckoview-quick-start). This guide may also be helpful if you find you’ve written a patch that requires changing GeckoView’s public API, see [Landing a Patch](#landing-a-patch).
|
||||
|
||||
Who this guide is not for: As mentioned above, if you are not already familiar with building Firefox for desktop, you’d likely be better served by our general bootstrapping guide. If you are looking to contribute to front-end development of one of Mozilla’s Android browsers, you’re likely better off starting with their codebase and returning here only if actual GeckoView changes are needed. See, for example, [Fenix’s GitHub](https://github.com/mozilla-mobile/fenix).
|
||||
|
||||
What to do if this guide contains bugs or leads you astray: The quickest way to get a response is to ask generally on #gv on Mozilla Slack; #mobile on Mozilla IRC may also work for the time being, albeit likely with slower response times. If you believe the guide needs updating, it would also be good to file a ticket to request that.
|
||||
|
||||
## Configuring the build system
|
||||
First, a quick note: This guide was written on MacOS 10.14; it should translate quite closely to other supported versions of MacOS and to Linux. Building GeckoView on Windows is not officially supported at the moment.
|
||||
To begin with, re-run `./mach bootstrap`; it will present you with options for the version of Firefox/GV that you want to build. Currently, option `3` is `GeckoView/Firefox for Android Artifact Mode` and `4` is `GeckoView/Firefox for Android`; if you’re here, you want one of these. The brief and approximately correct breakdown of `Artifact` vs regular builds for GeckoView is that `Artifact` builds will not allow you to work on native code, only on JS or Java.
|
||||
Once you’ve selected your build type, `bootstrap` should do its usual thing and grab whatever dependencies are necessary. You may need to agree to some licenses along the way. Once `bootstrap` has successfully completed, it will spit out a recommended `mozconfig`.
|
||||
|
||||
## Mozconfig and Building
|
||||
If you’ve followed from the previous section, `./mach bootstrap` printed out a recommended `mozconfig` that looks something like this:
|
||||
```
|
||||
# Build GeckoView/Firefox for Android:
|
||||
ac_add_options --enable-application=mobile/android
|
||||
|
||||
# Targeting the following architecture.
|
||||
# For regular phones, no --target is needed.
|
||||
# For x86 emulators (and x86 devices, which are uncommon):
|
||||
# ac_add_options --target=i686
|
||||
# For newer phones.
|
||||
# ac_add_options --target=aarch64
|
||||
# For x86_64 emulators (and x86_64 devices, which are even less common):
|
||||
# ac_add_options --target=x86_64
|
||||
```
|
||||
As written, this defaults to building for a 32-bit ARM architecture, which is probably not what you want. If you intend to work on an actual device, you almost certainly want a 64-bit ARM build, as it is supported by virtually all modern ARM phones/tablets and is the only ARM build we ship on the Google Play Store. To go this route, uncomment the `ac_add_options --target=aarch64` line in the `mozconfig`. On the other hand, x86-64 emulated devices are widely used by the GeckoView team and are used extensively on `try`; if you intend to use an emulator, uncomment the `ac_add_options --target=x86_64` line in the `mozconfig`. Don’t worry about installing an emulator at the moment, that will be covered shortly.
|
||||
It’s worth noting here that other `mozconfig` options will generally work as you’d expect. Additionally, if you plan on debugging native code on Android, you should include the `mozconfig` changes mentioned [here](native-debugging).
|
||||
Now, using that `mozconfig` with any modifications you’ve made, simply `./mach build`. If all goes well, you will have successfully built GeckoView.
|
||||
|
||||
## Installing, Running, and Using in Fenix/AC
|
||||
An (x86-64) emulator is the most common and developer-friendly way of contributing to GeckoView in most cases. If you're going to go this route, simply run `./mach android-emulator` — by default, this will install and launch an x86-64 Android emulator running the same Android 7.0 image that is used on `try`. If you need a different emulator image you can run `./mach android-emulator --help` for information on what Android images are available via `mach`. You can also install an emulator image via Android Studio.
|
||||
In cases where an emulator may not suffice (eg graphics or performance testing), or if you'd simply prefer not to use an emulator, you can opt to use an actual phone instead. To do so, you’ll need to enable `USB Debugging` on your phone if you haven’t already. On most modern Android devices, you can do this by opening `Settings`, going to `About phone`, and tapping `Build number` seven times. You should get a notification informing you that you’ve unlocked developer options. Now return to `Settings`, go to `Developer options`, and enable USB debugging.
|
||||
|
||||
### GeckoView Example App
|
||||
Now that you’ve connected a phone or setup an emulator, the simplest way to test GeckoView is to launch the GeckoView Example app by running `./mach run` (or install it with `./mach install` and run it yourself). This is a simplistic GV-based browser that lives in the tree; in many cases, it is sufficient to test and debug Gecko changes, and is by far the simplest way of doing so. It supports remote debugging by default — simply open Remote Debugging on your desktop browser and the connected device/emulator should show up when the example app is open. You can also use the example app for native debugging, follow instructions [here](native-debugging).
|
||||
|
||||
### GeckoView JUnit Tests
|
||||
Once you’ve successfully built GV, you can run tests from the GeckoView JUnit test suite with `./mach geckoview-junit`. For further examples (eg running individual tests, repeating tests, etc.), consult the [quick start guide](geckoview-quick-start#running-tests-locally).
|
||||
|
||||
### Fenix and other GV-based Apps
|
||||
If you are working on something for which the GeckoView Example app is not sufficient for some reason, you may need to use your local build of GeckoView in one of Mozilla’s GV-based apps like Fenix. For instructions on that, see [here](geckoview-quick-start#include-geckoview-as-a-dependency).
|
||||
|
||||
## Debugging
|
||||
|
||||
### Remote Debugging
|
||||
To recap a bit of the above, in the GeckoView Example app, remote debugging is enabled by default, and your device should show up in your desktop browser’s Remote Debugging window with no special effort. For Fenix, you can enable remote debugging by opening the three-dot menu and toggling `Remote debugging via USB` under `Developer tools`; other Mozilla GV-based browsers have similar options.
|
||||
|
||||
### Native Debugging
|
||||
To perform native debugging on any GV app will require you to install Android Studio and follow instructions [here](native-debugging).
|
||||
|
||||
## Landing a Patch
|
||||
In most cases, there shouldn’t be anything out of the ordinary to deal with when landing a patch that affects GeckoView; make sure you include Android in your `try` runs and you should be good. However, if you need to alter the GeckoView public API in any way — essentially anything that’s exposed as `public` in GeckoView Java files — then you’ll find that you need to run the API linter and update the change log. To do this, first run `./mach lint --linter android-api-lint` — if you have indeed changed the public API, this will give you a `gradle` command to run that will give further instructions. GeckoView API changes require two reviews from GeckoView team members; you can open it up to the team in general by adding `#geckoview-reviewers` as a reviewer on Phabricator.
|
|
@ -1,179 +0,0 @@
|
|||
.. -*- Mode: rst; fill-column: 80; -*-
|
||||
=============================
|
||||
GeckoView For Gecko Engineers
|
||||
=============================
|
||||
|
||||
Table of contents
|
||||
=================
|
||||
|
||||
.. contents:: :local:
|
||||
|
||||
GeckoView for Gecko Engineers
|
||||
=============================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
Who this guide is for: As the title suggests, the target audience of
|
||||
this guide is existing Gecko engineers who need to be able to build and
|
||||
(locally) test GeckoView. If you aren’t already familiar with building
|
||||
Firefox on a desktop platform, you’ll likely be better served by reading
|
||||
`our general introduction <geckoview-quick-start>`_. This guide may
|
||||
also be helpful if you find you’ve written a patch that requires
|
||||
changing GeckoView’s public API, see `Landing a
|
||||
Patch <#landing-a-patch>`_.
|
||||
|
||||
Who this guide is not for: As mentioned above, if you are not already
|
||||
familiar with building Firefox for desktop, you’d likely be better
|
||||
served by our general bootstrapping guide. If you are looking to
|
||||
contribute to front-end development of one of Mozilla’s Android
|
||||
browsers, you’re likely better off starting with their codebase and
|
||||
returning here only if actual GeckoView changes are needed. See, for
|
||||
example, `Fenix’s GitHub <https://github.com/mozilla-mobile/fenix>`_.
|
||||
|
||||
What to do if this guide contains bugs or leads you astray: The quickest
|
||||
way to get a response is to ask generally on #gv on Mozilla Slack;
|
||||
#mobile on Mozilla IRC may also work for the time being, albeit likely
|
||||
with slower response times. If you believe the guide needs updating, it
|
||||
would also be good to file a ticket to request that.
|
||||
|
||||
Configuring the build system
|
||||
----------------------------
|
||||
|
||||
First, a quick note: This guide was written on MacOS 10.14; it should
|
||||
translate quite closely to other supported versions of MacOS and to
|
||||
Linux. Building GeckoView on Windows is not officially supported at the
|
||||
moment. To begin with, re-run ``./mach bootstrap``; it will present you
|
||||
with options for the version of Firefox/GV that you want to build.
|
||||
Currently, option ``3`` is
|
||||
``GeckoView/Firefox for Android Artifact Mode`` and ``4`` is
|
||||
``GeckoView/Firefox for Android``; if you’re here, you want one of
|
||||
these. The brief and approximately correct breakdown of ``Artifact`` vs
|
||||
regular builds for GeckoView is that ``Artifact`` builds will not allow
|
||||
you to work on native code, only on JS or Java. Once you’ve selected
|
||||
your build type, ``bootstrap`` should do its usual thing and grab
|
||||
whatever dependencies are necessary. You may need to agree to some
|
||||
licenses along the way. Once ``bootstrap`` has successfully completed,
|
||||
it will spit out a recommended ``mozconfig``.
|
||||
|
||||
Mozconfig and Building
|
||||
----------------------
|
||||
|
||||
If you’ve followed from the previous section, ``./mach bootstrap``
|
||||
printed out a recommended ``mozconfig`` that looks something like this:
|
||||
|
||||
::
|
||||
|
||||
# Build GeckoView/Firefox for Android:
|
||||
ac_add_options --enable-application=mobile/android
|
||||
|
||||
# Targeting the following architecture.
|
||||
# For regular phones, no --target is needed.
|
||||
# For x86 emulators (and x86 devices, which are uncommon):
|
||||
# ac_add_options --target=i686
|
||||
# For newer phones.
|
||||
# ac_add_options --target=aarch64
|
||||
# For x86_64 emulators (and x86_64 devices, which are even less common):
|
||||
# ac_add_options --target=x86_64
|
||||
|
||||
As written, this defaults to building for a 32-bit ARM architecture,
|
||||
which is probably not what you want. If you intend to work on an actual
|
||||
device, you almost certainly want a 64-bit ARM build, as it is supported
|
||||
by virtually all modern ARM phones/tablets and is the only ARM build we
|
||||
ship on the Google Play Store. To go this route, uncomment the
|
||||
``ac_add_options --target=aarch64`` line in the ``mozconfig``. On the
|
||||
other hand, x86-64 emulated devices are widely used by the GeckoView
|
||||
team and are used extensively on ``try``; if you intend to use an
|
||||
emulator, uncomment the ``ac_add_options --target=x86_64`` line in the
|
||||
``mozconfig``. Don’t worry about installing an emulator at the moment,
|
||||
that will be covered shortly. It’s worth noting here that other
|
||||
``mozconfig`` options will generally work as you’d expect. Additionally,
|
||||
if you plan on debugging native code on Android, you should include the
|
||||
``mozconfig`` changes mentioned `in our native debugging guide <native-debugging.html>`_. Now, using
|
||||
that ``mozconfig`` with any modifications you’ve made, simply
|
||||
``./mach build``. If all goes well, you will have successfully built
|
||||
GeckoView.
|
||||
|
||||
Installing, Running, and Using in Fenix/AC
|
||||
------------------------------------------
|
||||
|
||||
An (x86-64) emulator is the most common and developer-friendly way of
|
||||
contributing to GeckoView in most cases. If you’re going to go this
|
||||
route, simply run ``./mach android-emulator`` — by default, this will
|
||||
install and launch an x86-64 Android emulator running the same Android
|
||||
7.0 image that is used on ``try``. If you need a different emulator
|
||||
image you can run ``./mach android-emulator --help`` for information on
|
||||
what Android images are available via ``mach``. You can also install an
|
||||
emulator image via Android Studio. In cases where an emulator may not
|
||||
suffice (eg graphics or performance testing), or if you’d simply prefer
|
||||
not to use an emulator, you can opt to use an actual phone instead. To
|
||||
do so, you’ll need to enable ``USB Debugging`` on your phone if you
|
||||
haven’t already. On most modern Android devices, you can do this by
|
||||
opening ``Settings``, going to ``About phone``, and tapping
|
||||
``Build number`` seven times. You should get a notification informing
|
||||
you that you’ve unlocked developer options. Now return to ``Settings``,
|
||||
go to ``Developer options``, and enable USB debugging.
|
||||
|
||||
GeckoView Example App
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Now that you’ve connected a phone or setup an emulator, the simplest way
|
||||
to test GeckoView is to launch the GeckoView Example app by running
|
||||
``./mach run`` (or install it with ``./mach install`` and run it
|
||||
yourself). This is a simplistic GV-based browser that lives in the tree;
|
||||
in many cases, it is sufficient to test and debug Gecko changes, and is
|
||||
by far the simplest way of doing so. It supports remote debugging by
|
||||
default — simply open Remote Debugging on your desktop browser and the
|
||||
connected device/emulator should show up when the example app is open.
|
||||
You can also use the example app for native debugging, follow
|
||||
instructions `here <native-debugging.html>`_.
|
||||
|
||||
GeckoView JUnit Tests
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Once you’ve successfully built GV, you can run tests from the GeckoView
|
||||
JUnit test suite with ``./mach geckoview-junit``. For further examples
|
||||
(eg running individual tests, repeating tests, etc.), consult the `quick
|
||||
start guide <geckoview-quick-start.html#running-tests-locally>`_.
|
||||
|
||||
Fenix and other GV-based Apps
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you are working on something for which the GeckoView Example app is
|
||||
not sufficient for some reason, you may need to `use your local build of
|
||||
GeckoView in one of Mozilla’s GV-based apps like Fenix <geckoview-quick-start.html#include-geckoview-as-a-dependency>`_.
|
||||
|
||||
Debugging
|
||||
---------
|
||||
|
||||
Remote Debugging
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
To recap a bit of the above, in the GeckoView Example app, remote
|
||||
debugging is enabled by default, and your device should show up in your
|
||||
desktop browser’s Remote Debugging window with no special effort. For
|
||||
Fenix, you can enable remote debugging by opening the three-dot menu and
|
||||
toggling ``Remote debugging via USB`` under ``Developer tools``; other
|
||||
Mozilla GV-based browsers have similar options.
|
||||
|
||||
Native Debugging
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
To perform native debugging on any GV app will require you to install
|
||||
Android Studio and follow instructions `here <native-debugging.html>`_.
|
||||
|
||||
Landing a Patch
|
||||
---------------
|
||||
|
||||
In most cases, there shouldn’t be anything out of the ordinary to deal
|
||||
with when landing a patch that affects GeckoView; make sure you include
|
||||
Android in your ``try`` runs and you should be good. However, if you
|
||||
need to alter the GeckoView public API in any way — essentially anything
|
||||
that’s exposed as ``public`` in GeckoView Java files — then you’ll find
|
||||
that you need to run the API linter and update the change log. To do
|
||||
this, first run ``./mach lint --linter android-api-lint`` — if you have
|
||||
indeed changed the public API, this will give you a ``gradle`` command
|
||||
to run that will give further instructions. GeckoView API changes
|
||||
require two reviews from GeckoView team members; you can open it up to
|
||||
the team in general by adding ``#geckoview-reviewers`` as a reviewer on
|
||||
Phabricator.
|
|
@ -0,0 +1,198 @@
|
|||
---
|
||||
layout: default
|
||||
title: GeckoView Contributor Guide
|
||||
summary: Guide to setting up as a contributor to GeckoView.
|
||||
tags: [GeckoView,Gecko,mozilla,android,WebView,mobile,mozilla-central,setup,get started,compile,build,deploy,bug fix,submit,patch,arcanist,arc,moz-phab,phabricator]
|
||||
nav_exclude: true
|
||||
exclude: true
|
||||
---
|
||||
## Table of contents
|
||||
{: .no_toc .text-delta }
|
||||
|
||||
1. TOC
|
||||
{:toc}
|
||||
|
||||
# GeckoView Contributor Quick Start Guide
|
||||
|
||||
This is a guide for developers who want to contribute to the GeckoView project. If you want to get started using GeckoView in your app then you should refer to the [wiki](https://wiki.mozilla.org/Mobile/GeckoView#Get_Started).
|
||||
|
||||
You may also be interested in how to get up and running with [Firefox For Android](https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Build_Instructions/Simple_Firefox_for_Android_build).
|
||||
|
||||
## Get set up with Mozilla Central
|
||||
|
||||
The GeckoView codebase is part of the main Firefox tree and can be found in `mozilla-central`. You will need to get set up as a contributor to Firefox in order to contribute to GeckoView. To get set up with `mozilla-central`, follow the [Quick Start Guide for Git Users](mc-quick-start), or the [Contributing to the Mozilla code base](https://developer.mozilla.org/docs/Mozilla/Developer_guide/Introduction) guide on [MDN](https://developer.mozilla.org/) for Mercurial users.
|
||||
|
||||
Once you have a copy of `mozilla-central`, you will need to build GeckoView.
|
||||
|
||||
## Bootstrap Gecko
|
||||
Bootstrap configures everything for GeckoView and Fennec development.
|
||||
|
||||
* Ensure you have `mozilla-central` checked out. If this is the first time you are doing this, it may take some time.
|
||||
|
||||
```bash
|
||||
git checkout central/default
|
||||
```
|
||||
If you are on a mac, you will need to have the Xcode build tools installed. You can do this by either [installing Xcode](https://developer.apple.com/xcode/) or installing only the tools from the command line by running `xcode-select --install` and following the on screen instructions. Use the ` --no-interactive` argument to automatically accept any license agreements.
|
||||
|
||||
```bash
|
||||
./mach bootstrap [ --no-interactive]
|
||||
```
|
||||
* Choose option `4. Firefox for Android` for GeckoView development. This will give you a version of Gecko configured for Android that has not bundled the native code into embedded libraries so you can amend the code.
|
||||
* Say Y to all configuration options
|
||||
* Once `mach bootstrap` is complete it will tell you to copy and paste some configuration into your `mozconfig` file. The `mozconfig` file can be found in the root of your `gecko` repo - or create a file called `mozconfig` if it does not exist. Check that the correct value is associated with the `--target` argument as this may not correctly match your setup. Copy the file contents from the `mach bootstrap` output into your file and save in the root directory of your project.
|
||||
|
||||
## Build from the command line
|
||||
|
||||
In order to pick up the configuration changes we just made we need to build from the command line. This will update generated sources, compile native code, and produce GeckoView AARs and example and test APKs.
|
||||
|
||||
```bash
|
||||
./mach build
|
||||
```
|
||||
|
||||
## Build Using Android Studio
|
||||
|
||||
* Install [Android Studio](https://developer.android.com/studio/install).
|
||||
* Disable Instant Run. This is because Fennec and the Geckoview Example app cannot deploy with Instant Run on.
|
||||
* Select Android Studio > Preferences from the menu bar
|
||||
* Navigate to Build, Execution, Deployment > Instant Run.
|
||||
* Uncheck the box that reads `Enable Instant Run to hot swap code/resource changes on deploy`.
|
||||
|
||||
![alt text]({{ site.url }}/assets/DisableInstantRun.png "Disable Instant Run")
|
||||
* Choose File->Open from the toolbar
|
||||
* Navigate to the root of your `mozilla-central` source directory and click "Open"
|
||||
* Click yes if it asks if you want to use the gradle wrapper.
|
||||
* If the gradle sync does not automatically start, select File > Sync Project with Gradle Files.
|
||||
* Wait for the project to index and gradle to sync. Once synced, the workspace will reconfigure to display the different projects.
|
||||
* annotations contains custom annotations used inside GeckoView and Fennec.
|
||||
* app is Fennec - Firefox for Android. Here is where you will find code specific to that app.
|
||||
* geckoview is the GeckoView project. Here is all the Java files related to GeckoView
|
||||
* geckoview_example is an example browser built using GeckoView.
|
||||
* omnijar contains the parts of Gecko and GeckoView that are not written in Java or Kotlin
|
||||
* thirdparty contains third party code that Fennec and GeckoView use.
|
||||
|
||||
![alt text]({{ site.url }}/assets/GeckoViewStructure.png "GeckoView Structure")
|
||||
|
||||
Now you're set up and ready to go.
|
||||
|
||||
**Important: at this time, building from Android Studio or directly from Gradle does not (re-)compile native code, including C++ and Rust.** This means you will need to run `mach build` yourself to pick up changes to native code. [Bug 1509539](https://bugzilla.mozilla.org/show_bug.cgi?id=1509539) tracks making Android Studio and Gradle do this automatically.
|
||||
|
||||
## Performing a bug fix
|
||||
|
||||
One you have got GeckoView building and running, you will want to start contributing. There is a general guide to [Performing a Bug Fix for Git Developers](contributing-to-mc) for you to follow. To contribute to GeckoView specifically, you will need the following additional information.
|
||||
|
||||
### Running tests and linter locally
|
||||
|
||||
To ensure that your patch does not break existing functionality in GeckoView, you can run the junit test suite with the following command
|
||||
|
||||
```
|
||||
./mach geckoview-junit
|
||||
```
|
||||
|
||||
This command also allows you to run individual tests or test classes, e.g.
|
||||
|
||||
```
|
||||
./mach geckoview-junit org.mozilla.geckoview.test.NavigationDelegateTest
|
||||
./mach geckoview-junit org.mozilla.geckoview.test.NavigationDelegateTest#loadUnknownHost
|
||||
```
|
||||
|
||||
If your patch makes a GeckoView JavaScript module, you should run ESLint as well:
|
||||
|
||||
```
|
||||
./mach lint -l eslint mobile/android/modules/geckoview/
|
||||
```
|
||||
|
||||
To see information on other options, simply run `./mach geckoview-junit --help`; of particular note for dealing with intermittent test failures are `--repeat N` and `--run-until-failure`, both of which do exactly what you’d expect.
|
||||
|
||||
If you use Android Studio, and the emulator had been started by Android Studio, you will find the logcat output for the test in Android Studio (Logcat tab at the bottom), even if you start the test from your terminal.
|
||||
|
||||
To see logcat output in terminal, run the test in one terminal window, and `adb logcat` in another terminal window. Make sure that output of `which adb` includes .mozbuild. If it doesn't, add path to mozbuild tools to your PATH: `export PATH=$HOME/.mozbuild/android-sdk-<your OS - e.g. macos or linux>/platform-tools:$PATH`. Make sure to start the emulator from the terminal (if it had not been started, ``./mach geckoview-junit` will ask you if you want to start the emulator - say YES. Alternatively, you can run `./mach android-emulator` before `./mach geckoview-junit`).
|
||||
|
||||
### Updating the changelog and API documentation
|
||||
|
||||
If the patch that you want to submit changes the public API for GeckoView, you must ensure that the API documentation is kept up to date. To check whether your patch has altered the API, run the following command.
|
||||
|
||||
```bash
|
||||
./mach lint --linter android-api-lint
|
||||
```
|
||||
|
||||
The output of this command will inform you if any changes you have made break the existing API. Review the changes and follow the instructions it provides.
|
||||
|
||||
If the linter asks you to update the changelog, please ensure that you follow the correct format for changelog entries. Under the heading for the next release version, add a new entry for the changes that you are making to the API, along with links to any relevant files, and bug number e.g.
|
||||
|
||||
{% raw %}
|
||||
```
|
||||
- Added [`GeckoRuntimeSettings.Builder#aboutConfigEnabled`][71.12] to control whether or
|
||||
not `about:config` should be available.
|
||||
([bug 1540065]({{bugzilla}}1540065))
|
||||
|
||||
[71.12]: {{javadoc_uri}}/GeckoRuntimeSettings.Builder.html#aboutConfigEnabled-boolean-
|
||||
```
|
||||
{% endraw %}
|
||||
|
||||
### Submitting to the `try` server
|
||||
|
||||
It is advisable to run your tests before submitting your patch. You can do this using Mozilla's `try` server. To submit a GeckoView patch to `try` before submitting it for review, type:
|
||||
```bash
|
||||
./mach try fuzzy -q "android"
|
||||
```
|
||||
|
||||
This will run all of the Android test suite. If your patch passes on `try` you can be (fairly) confident that it will land successfully after review.
|
||||
|
||||
### Tagging a reviewer
|
||||
|
||||
When submitting a patch to Phabricator, if you know who you want to review your patch, put their Phabricator handle against the `reviewers` field.
|
||||
|
||||
If you don't know who to tag for a review in the Phabricator submission message, leave the field blank and, after submission, follow the link to the patch in Phabricator and scroll to the bottom of the screen until you see the comment box.
|
||||
* Select the `Add Action` drop down and pick the `Change Reviewers` option.
|
||||
* In the presented box, add `geckoview-reviewers`. Selecting this group as the reviewer will notify all the members of the GeckoView team there is a patch to review.
|
||||
* Click `Submit` to submit the reviewer change request.
|
||||
|
||||
## Include GeckoView as a dependency
|
||||
|
||||
If you want to include a development version of GeckoView as a dependency inside another app, you must link to a local copy. There are several ways to achieve this, but the preferred way is to use Gradle's *dependency substitution* mechanism, for which there is first-class support in `mozilla-central` and a pattern throughout Mozilla's GeckoView-consuming ecosystem.
|
||||
|
||||
The good news is that `mach build` produces everything you need, so that after the configuration below, you should find that the following commands rebuild your local GeckoView and then consume your local version in the downstream project.
|
||||
|
||||
```sh
|
||||
cd /path/to/mozilla-central && ./mach build
|
||||
cd /path/to/project && ./gradlew assembleDebug
|
||||
```
|
||||
|
||||
**Be sure that your `mozconfig` specifies the correct `--target` argument for your target device.** Many projects use "ABI splitting" to include only the target device's native code libraries in APKs deployed to the device. On x86-64 and aarch64 devices, this can result in GeckoView failing to find any libraries, because valid x86 and ARM libraries were not included in a deployed APK. Avoid this by setting `--target` to the exact ABI that your device supports.
|
||||
|
||||
### Dependency substiting your local GeckoView into a Mozilla project
|
||||
|
||||
Most GeckoView-consuming projects produced by Mozilla support dependency substitution via `local.properties`. These projects include:
|
||||
* [Fenix](https://github.com/mozilla-mobile/fenix)
|
||||
* [reference-browser](https://github.com/mozilla-mobile/reference-browser)
|
||||
* [android-components](https://github.com/mozilla-mobile/android-components)
|
||||
* [Firefox Reality](https://github.com/MozillaReality/FirefoxReality)
|
||||
|
||||
Simply edit (or create) the file `local.properties` in the project root and include a line like:
|
||||
```properties
|
||||
dependencySubstitutions.geckoviewTopsrcdir=/path/to/mozilla-central
|
||||
```
|
||||
The default object directory -- the one that a plain `mach build` discovers -- will be used. You can optionally specify a particular object directory with an additional line like:
|
||||
```properties
|
||||
dependencySubstitutions.geckoviewTopobjdir=/path/to/object-directory
|
||||
```
|
||||
|
||||
With these lines, the GeckoView-consuming project should use the GeckoView AAR produced by `mach build` in your local `mozilla-central`.
|
||||
|
||||
**Remember to remove the lines in `local.properties` when you want to return to using the published GeckoView builds!**
|
||||
|
||||
### Dependency substituting your local GeckoView into a non-Mozilla project
|
||||
|
||||
In projects that don't have first-class support for dependency substitution already, you can do the substitution yourself. See the documentation in [substitue-local-geckoview.gradle](https://hg.mozilla.org/mozilla-central/file/tip/substitute-local-geckoview.gradle), but roughly: in each Gradle project that consumes GeckoView, i.e., in each `build.gradle` with a `dependencies { ... 'org.mozilla.geckoview:geckoview-...' }` block, include lines like:
|
||||
|
||||
```groovy
|
||||
ext.topsrcdir = "/path/to/mozilla-central"
|
||||
ext.topobjdir = "/path/to/object-directory" // Optional.
|
||||
apply from: "${topsrcdir}/substitute-local-geckoview.gradle"
|
||||
```
|
||||
|
||||
**Remember to remove the lines from all `build.gradle` files when you want to return to using the published GeckoView builds!**
|
||||
|
||||
## Next Steps
|
||||
|
||||
- Get started with [Native Debugging](native-debugging)
|
|
@ -1,324 +0,0 @@
|
|||
.. -*- Mode: rst; fill-column: 80; -*-
|
||||
===========================
|
||||
GeckoView Contributor Guide
|
||||
===========================
|
||||
|
||||
Table of contents
|
||||
=================
|
||||
|
||||
.. contents:: :local:
|
||||
|
||||
GeckoView Contributor Quick Start Guide
|
||||
=======================================
|
||||
|
||||
This is a guide for developers who want to contribute to the GeckoView
|
||||
project. If you want to get started using GeckoView in your app then you
|
||||
should refer to the
|
||||
`wiki <https://wiki.mozilla.org/Mobile/GeckoView#Get_Started>`_.
|
||||
|
||||
You may also be interested in how to get up and running with `Firefox
|
||||
For
|
||||
Android <https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Build_Instructions/Simple_Firefox_for_Android_build>`_.
|
||||
|
||||
Get set up with Mozilla Central
|
||||
-------------------------------
|
||||
|
||||
The GeckoView codebase is part of the main Firefox tree and can be found
|
||||
in ``mozilla-central``. You will need to get set up as a contributor to
|
||||
Firefox in order to contribute to GeckoView. To get set up with
|
||||
``mozilla-central``, follow the `Quick Start Guide for Git
|
||||
Users <mc-quick-start.html>`_, or the `Contributing to the Mozilla code
|
||||
base <https://developer.mozilla.org/docs/Mozilla/Developer_guide/Introduction>`_
|
||||
guide on `MDN <https://developer.mozilla.org/>`_ for Mercurial users.
|
||||
|
||||
Once you have a copy of ``mozilla-central``, you will need to build
|
||||
GeckoView.
|
||||
|
||||
Bootstrap Gecko
|
||||
---------------
|
||||
|
||||
Bootstrap configures everything for GeckoView and Fennec (Firefox for Android) development.
|
||||
|
||||
- Ensure you have ``mozilla-central`` checked out. If this is the first
|
||||
time you are doing this, it may take some time.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
git checkout central/default
|
||||
|
||||
If you are on a mac, you will need to have the Xcode build tools
|
||||
installed. You can do this by either `installing
|
||||
Xcode <https://developer.apple.com/xcode/>`__ or installing only the
|
||||
tools from the command line by running ``xcode-select --install`` and
|
||||
following the on screen instructions. Use the ``--no-interactive``
|
||||
argument to automatically accept any license agreements.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
./mach bootstrap [ --no-interactive]
|
||||
|
||||
- Choose option \`4. Firefox for Android\` for GeckoView development.
|
||||
This will give you a version of Gecko configured for Android that has
|
||||
not bundled the native code into embedded libraries so you can amend
|
||||
the code.
|
||||
- Say Y to all configuration options
|
||||
- Once ``mach bootstrap`` is complete it will tell you to copy and
|
||||
paste some configuration into your ``mozconfig`` file. The
|
||||
``mozconfig`` file can be found in the root of your ``gecko`` repo -
|
||||
or create a file called ``mozconfig`` if it does not exist. Check
|
||||
that the correct value is associated with the ``--target`` argument
|
||||
as this may not correctly match your setup. Copy the file contents
|
||||
from the ``mach bootstrap`` output into your file and save in the
|
||||
root directory of your project.
|
||||
|
||||
Build from the command line
|
||||
---------------------------
|
||||
|
||||
In order to pick up the configuration changes we just made we need to
|
||||
build from the command line. This will update generated sources, compile
|
||||
native code, and produce GeckoView AARs and example and test APKs.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
./mach build
|
||||
|
||||
Build Using Android Studio
|
||||
--------------------------
|
||||
|
||||
- Install `Android
|
||||
Studio <https://developer.android.com/studio/install>`_.
|
||||
- Disable Instant Run. This is because Fennec and the Geckoview Example
|
||||
app cannot deploy with Instant Run on.
|
||||
|
||||
- Select Android Studio > Preferences from the menu bar
|
||||
- Navigate to Build, Execution, Deployment > Instant Run.
|
||||
- Uncheck the box that reads
|
||||
``Enable Instant Run to hot swap code/resource changes on deploy``.
|
||||
|
||||
|alt text|
|
||||
- Choose File->Open from the toolbar
|
||||
- Navigate to the root of your ``mozilla-central`` source directory and
|
||||
click “Open”
|
||||
- Click yes if it asks if you want to use the gradle wrapper.
|
||||
|
||||
- If the gradle sync does not automatically start, select File >
|
||||
Sync Project with Gradle Files.
|
||||
|
||||
- Wait for the project to index and gradle to sync. Once synced, the
|
||||
workspace will reconfigure to display the different projects.
|
||||
|
||||
- annotations contains custom annotations used inside GeckoView and
|
||||
Fennec.
|
||||
- app is Fennec - Firefox for Android. Here is where you will find
|
||||
code specific to that app.
|
||||
- geckoview is the GeckoView project. Here is all the Java files
|
||||
related to GeckoView
|
||||
- geckoview_example is an example browser built using GeckoView.
|
||||
- omnijar contains the parts of Gecko and GeckoView that are not
|
||||
written in Java or Kotlin
|
||||
- thirdparty contains third party code that Fennec and GeckoView
|
||||
use.
|
||||
|
||||
|alt text|
|
||||
|
||||
Now you’re set up and ready to go.
|
||||
|
||||
**Important: at this time, building from Android Studio or directly from
|
||||
Gradle does not (re-)compile native code, including C++ and Rust.** This
|
||||
means you will need to run ``mach build`` yourself to pick up changes to
|
||||
native code. `Bug
|
||||
1509539 <https://bugzilla.mozilla.org/show_bug.cgi?id=1509539>`_ tracks
|
||||
making Android Studio and Gradle do this automatically.
|
||||
|
||||
Performing a bug fix
|
||||
--------------------
|
||||
|
||||
One you have got GeckoView building and running, you will want to start
|
||||
contributing. There is a general guide to `Performing a Bug Fix for Git
|
||||
Developers <contributing-to-mc.html>`_ for you to follow. To contribute to
|
||||
GeckoView specifically, you will need the following additional
|
||||
information.
|
||||
|
||||
Running tests and linter locally
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To ensure that your patch does not break existing functionality in
|
||||
GeckoView, you can run the junit test suite with the following command
|
||||
|
||||
::
|
||||
|
||||
./mach geckoview-junit
|
||||
|
||||
This command also allows you to run individual tests or test classes,
|
||||
e.g.
|
||||
|
||||
::
|
||||
|
||||
./mach geckoview-junit org.mozilla.geckoview.test.NavigationDelegateTest
|
||||
./mach geckoview-junit org.mozilla.geckoview.test.NavigationDelegateTest#loadUnknownHost
|
||||
|
||||
If your patch makes a GeckoView JavaScript module, you should run ESLint
|
||||
as well:
|
||||
|
||||
::
|
||||
|
||||
./mach lint -l eslint mobile/android/modules/geckoview/
|
||||
|
||||
To see information on other options, simply run
|
||||
``./mach geckoview-junit --help``; of particular note for dealing with
|
||||
intermittent test failures are ``--repeat N`` and
|
||||
``--run-until-failure``, both of which do exactly what you’d expect.
|
||||
|
||||
Updating the changelog and API documentation
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If the patch that you want to submit changes the public API for
|
||||
GeckoView, you must ensure that the API documentation is kept up to
|
||||
date. To check whether your patch has altered the API, run the following
|
||||
command.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
./mach lint --linter android-api-lint
|
||||
|
||||
The output of this command will inform you if any changes you have made
|
||||
break the existing API. Review the changes and follow the instructions
|
||||
it provides.
|
||||
|
||||
If the linter asks you to update the changelog, please ensure that you
|
||||
follow the correct format for changelog entries. Under the heading for
|
||||
the next release version, add a new entry for the changes that you are
|
||||
making to the API, along with links to any relevant files, and bug
|
||||
number e.g.
|
||||
|
||||
::
|
||||
|
||||
- Added [`GeckoRuntimeSettings.Builder#aboutConfigEnabled`][71.12] to control whether or
|
||||
not `about:config` should be available.
|
||||
([bug 1540065]({{bugzilla}}1540065))
|
||||
|
||||
[71.12]: {{javadoc_uri}}/GeckoRuntimeSettings.Builder.html#aboutConfigEnabled-boolean-
|
||||
|
||||
Submitting to the ``try`` server
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
It is advisable to run your tests before submitting your patch. You can
|
||||
do this using Mozilla’s ``try`` server. To submit a GeckoView patch to
|
||||
``try`` before submitting it for review, type:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
./mach try fuzzy -q "android"
|
||||
|
||||
This will run all of the Android test suite. If your patch passes on
|
||||
``try`` you can be (fairly) confident that it will land successfully
|
||||
after review.
|
||||
|
||||
Tagging a reviewer
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
When submitting a patch to Phabricator, if you know who you want to
|
||||
review your patch, put their Phabricator handle against the
|
||||
``reviewers`` field.
|
||||
|
||||
If you don’t know who to tag for a review in the Phabricator submission
|
||||
message, leave the field blank and, after submission, follow the link to
|
||||
the patch in Phabricator and scroll to the bottom of the screen until
|
||||
you see the comment box.
|
||||
|
||||
- Select the ``Add Action`` drop down and pick
|
||||
the ``Change Reviewers`` option.
|
||||
- In the presented box, add
|
||||
``geckoview-reviewers``. Selecting this group as the reviewer will
|
||||
notify all the members of the GeckoView team there is a patch to review.
|
||||
- Click ``Submit`` to submit the reviewer change request.
|
||||
|
||||
Include GeckoView as a dependency
|
||||
---------------------------------
|
||||
|
||||
If you want to include a development version of GeckoView as a
|
||||
dependency inside another app, you must link to a local copy. There are
|
||||
several ways to achieve this, but the preferred way is to use Gradle’s
|
||||
*dependency substitution* mechanism, for which there is first-class
|
||||
support in ``mozilla-central`` and a pattern throughout Mozilla’s
|
||||
GeckoView-consuming ecosystem.
|
||||
|
||||
The good news is that ``mach build`` produces everything you need, so
|
||||
that after the configuration below, you should find that the following
|
||||
commands rebuild your local GeckoView and then consume your local
|
||||
version in the downstream project.
|
||||
|
||||
.. code:: sh
|
||||
|
||||
cd /path/to/mozilla-central && ./mach build
|
||||
cd /path/to/project && ./gradlew assembleDebug
|
||||
|
||||
**Be sure that your ``mozconfig`` specifies the correct ``--target``
|
||||
argument for your target device.** Many projects use “ABI splitting” to
|
||||
include only the target device’s native code libraries in APKs deployed
|
||||
to the device. On x86-64 and aarch64 devices, this can result in
|
||||
GeckoView failing to find any libraries, because valid x86 and ARM
|
||||
libraries were not included in a deployed APK. Avoid this by setting
|
||||
``--target`` to the exact ABI that your device supports.
|
||||
|
||||
Dependency substiting your local GeckoView into a Mozilla project
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Most GeckoView-consuming projects produced by Mozilla support dependency
|
||||
substitution via ``local.properties``. These projects include:
|
||||
|
||||
- `Fenix <https://github.com/mozilla-mobile/fenix>`_
|
||||
- `reference-browser <https://github.com/mozilla-mobile/reference-browser>`_
|
||||
- `android-components <https://github.com/mozilla-mobile/android-components>`_
|
||||
- `Firefox Reality <https://github.com/MozillaReality/FirefoxReality>`_
|
||||
|
||||
Simply edit (or create) the file ``local.properties`` in the project
|
||||
root and include a line like:
|
||||
|
||||
.. code:: properties
|
||||
|
||||
dependencySubstitutions.geckoviewTopsrcdir=/path/to/mozilla-central
|
||||
|
||||
The default object directory – the one that a plain ``mach build``
|
||||
discovers – will be used. You can optionally specify a particular object
|
||||
directory with an additional line like:
|
||||
|
||||
.. code:: properties
|
||||
|
||||
dependencySubstitutions.geckoviewTopobjdir=/path/to/object-directory
|
||||
|
||||
With these lines, the GeckoView-consuming project should use the
|
||||
GeckoView AAR produced by ``mach build`` in your local
|
||||
``mozilla-central``.
|
||||
|
||||
**Remember to remove the lines in ``local.properties`` when you want to
|
||||
return to using the published GeckoView builds!**
|
||||
|
||||
Dependency substituting your local GeckoView into a non-Mozilla project
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In projects that don’t have first-class support for dependency
|
||||
substitution already, you can do the substitution yourself. See the
|
||||
documentation in
|
||||
`substitue-local-geckoview.gradle <https://hg.mozilla.org/mozilla-central/file/tip/substitute-local-geckoview.gradle>`_,
|
||||
but roughly: in each Gradle project that consumes GeckoView, i.e., in
|
||||
each ``build.gradle`` with a
|
||||
``dependencies { ... 'org.mozilla.geckoview:geckoview-...' }`` block,
|
||||
include lines like:
|
||||
|
||||
.. code:: groovy
|
||||
|
||||
ext.topsrcdir = "/path/to/mozilla-central"
|
||||
ext.topobjdir = "/path/to/object-directory" // Optional.
|
||||
apply from: "${topsrcdir}/substitute-local-geckoview.gradle"
|
||||
|
||||
**Remember to remove the lines from all ``build.gradle`` files when you
|
||||
want to return to using the published GeckoView builds!**
|
||||
|
||||
Next Steps
|
||||
----------
|
||||
|
||||
- Get started with `Native Debugging <native-debugging.html>`_
|
||||
|
||||
.. |alt text| image:: ../assets/DisableInstantRun.png
|
||||
.. |alt text| image:: ../assets/GeckoViewStructure.png
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
layout: default
|
||||
title: Contributing to GeckoView
|
||||
nav_order: 4
|
||||
---
|
||||
|
||||
# Contributor Site
|
||||
|
||||
If you want to run GeckoView from code, or start contributing back to the project, here you will find resources to help you do that.
|
||||
|
||||
- [GeckoView Contributor Quick Start Guide](geckoview-quick-start): Get GeckoView set up for development.
|
||||
- [GeckoView for Gecko Engineers](for-gecko-engineers): A quick-start guide for those already familiar with contributing to Firefox development.
|
||||
- [Mozilla Central Quick Start Guide](mc-quick-start):
|
||||
Get Mozilla Central set up for development.
|
||||
- [Mozilla Central Contributor Guide](contributing-to-mc):
|
||||
Get started as a contributor to Mozilla Central.
|
||||
- [Guide to Native Debugging in Android Studio](native-debugging):
|
||||
Set up Android Studio for debugging native code.
|
||||
|
||||
If there is documentation that you feel is missing, or an existing document doesn't cover the aspect that you are looking for, please request it by raising an issue on our [documentation site](https://github.com/mozilla/geckoview/issues).
|
|
@ -1,37 +0,0 @@
|
|||
.. -*- Mode: rst; fill-column: 80; -*-
|
||||
=========================
|
||||
Contributing to GeckoView
|
||||
=========================
|
||||
|
||||
Contributor Site
|
||||
================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:hidden:
|
||||
|
||||
geckoview-quick-start
|
||||
for-gecko-engineers
|
||||
mc-quick-start
|
||||
contributing-to-mc
|
||||
native-debugging
|
||||
|
||||
If you want to run GeckoView from code, or start contributing back to
|
||||
the project, here you will find resources to help you do that.
|
||||
|
||||
- `GeckoView Contributor Quick Start Guide <geckoview-quick-start.html>`_:
|
||||
Get GeckoView set up for development.
|
||||
- `GeckoView for Gecko Engineers <for-gecko-engineers.html>`_: A
|
||||
quick-start guide for those already familiar with contributing to
|
||||
Firefox development.
|
||||
- `Mozilla Central Quick Start Guide <mc-quick-start.html>`_: Get Mozilla
|
||||
Central set up for development.
|
||||
- `Mozilla Central Contributor Guide <contributing-to-mc.html>`_: Get
|
||||
started as a contributor to Mozilla Central.
|
||||
- `Guide to Native Debugging in Android Studio <native-debugging.html>`_:
|
||||
Set up Android Studio for debugging native code.
|
||||
|
||||
If there is documentation that you feel is missing, or an existing
|
||||
document doesn’t cover the aspect that you are looking for, please
|
||||
request it by raising an issue on our `documentation
|
||||
site <https://github.com/mozilla/geckoview/issues>`_.
|
|
@ -0,0 +1,128 @@
|
|||
---
|
||||
layout: default
|
||||
title: Mozilla Central Quick Start
|
||||
summary: Guide to setting up as a Git contributor to mozilla-central.
|
||||
tags: [GeckoView,Gecko,mozilla,android,WebView,mobile,mozilla-central,setup,compiling,mercurial,git-cinnabar]
|
||||
nav_exclude: true
|
||||
exclude: true
|
||||
---
|
||||
## Table of contents
|
||||
{: .no_toc .text-delta }
|
||||
|
||||
1. TOC
|
||||
{:toc}
|
||||
|
||||
# Firefox Developer Git Quick Start Guide
|
||||
|
||||
Getting setup to as a first time Mozilla contributor is hard. There are plenty of guides out there to help you get started as a contributor, but many of the new contributor guides out of date often more current ones are aimed at more experienced contributors. If you want to review these guides, you can find several linked to from [Contributing to the Mozilla code base](https://developer.mozilla.org/docs/Mozilla/Developer_guide/Introduction) on [MDN](https://developer.mozilla.org/).
|
||||
|
||||
This guide will take you through setting up as a contributor to `mozilla-central`, the Firefox main repository, as a git user.
|
||||
|
||||
## Setup
|
||||
|
||||
The first thing you will need is to install Mercurial as this is the VCS that `mozilla-central` uses.
|
||||
|
||||
### Mac
|
||||
|
||||
#### Homebrew
|
||||
|
||||
```bash
|
||||
brew install mercurial
|
||||
```
|
||||
|
||||
#### macports
|
||||
|
||||
```bash
|
||||
sudo port install mercurial
|
||||
```
|
||||
|
||||
### Linux
|
||||
|
||||
#### apt
|
||||
|
||||
```bash
|
||||
sudo apt-get install mercurial
|
||||
```
|
||||
|
||||
Alternatively you can install [Mercurial directly](https://www.mercurial-scm.org/wiki/Download).
|
||||
|
||||
Check that you have successfully installed Mercurial by running:
|
||||
```bash
|
||||
hg --version
|
||||
```
|
||||
|
||||
If you are an experienced git user and are unfamiliar with Mercurial, you may want to install `git-cinnabar`. Cinnabar is a git remote helper that allows you to interact with Mercurial repos using git semantics.
|
||||
|
||||
## git-cinnabar
|
||||
|
||||
There is a Homebrew install option for `git-cinnabar`, but this did not work for me, nor did the installer option. Using these tools, when I tried to clone the Mercurial repo it hung and did not complete. I had to do a manual install before I could use `git-cinnabar` successfully to download a Mercurial repo. If you would like to try either of these option, however, here they are:
|
||||
|
||||
### Mac
|
||||
#### Homebrew
|
||||
|
||||
```bash
|
||||
brew install git-cinnabar
|
||||
```
|
||||
|
||||
### All Platforms
|
||||
#### Installer
|
||||
|
||||
```bash
|
||||
git cinnabar download
|
||||
```
|
||||
|
||||
#### Manual installation
|
||||
|
||||
```bash
|
||||
git clone https://github.com/glandium/git-cinnabar.git && cd git-cinnabar
|
||||
make
|
||||
export PATH="$PATH:/somewhere/git-cinnabar"
|
||||
echo 'export PATH="$PATH:/somewhere/git-cinnabar"' >> ~/.bash_profile
|
||||
git cinnabar download
|
||||
```
|
||||
|
||||
`git-cinnabar`'s creator, [glandium](https://glandium.org/), has written a number of posts about setting up for Firefox Development with git. This [post](https://glandium.org/blog/?page_id=3438) is the one that has formed the basis for this walkthrough.
|
||||
|
||||
In synopsis:
|
||||
|
||||
* initialize an empty git repository
|
||||
```bash
|
||||
git init gecko && cd gecko
|
||||
```
|
||||
|
||||
* Configure git:
|
||||
|
||||
```bash
|
||||
git config fetch.prune true
|
||||
git config push.default upstream
|
||||
```
|
||||
|
||||
* Add remotes for your repositories. There are several to choose from, `central`, `inbound`, `beta`, `release` etc. but in reality, if you plan on using Phabricator, which is Firefox's preferred patch submission system, you only need to set up `central`. It might be advisable to have access to `inbound` however, if you want to work on a version of Firefox that is queued for release. This guide will be focused on Phabricator.
|
||||
|
||||
```bash
|
||||
git remote add central hg::https://hg.mozilla.org/mozilla-central -t branches/default/tip
|
||||
git remote add inbound hg::https://hg.mozilla.org/integration/mozilla-inbound -t branches/default/tip
|
||||
git remote set-url --push central hg::ssh://hg.mozilla.org/mozilla-central
|
||||
git remote set-url --push inbound hg::ssh://hg.mozilla.org/integration/mozilla-inbound
|
||||
```
|
||||
* Expose the branch tip to get quick access with some easy names.
|
||||
|
||||
```bash
|
||||
git config remote.central.fetch +refs/heads/branches/default/tip:refs/remotes/central/default
|
||||
git config remote.inbound.fetch +refs/heads/branches/default/tip:refs/remotes/inbound/default
|
||||
```
|
||||
* Setup a remote for the try server. The try server is an easy way to test a patch without actually checking the patch into the core repository. Your code will go through the same tests as a `mozilla-central` push, and you'll be able to download builds if you wish.
|
||||
|
||||
```bash
|
||||
git remote add try hg::https://hg.mozilla.org/try
|
||||
git config remote.try.skipDefaultUpdate true
|
||||
git remote set-url --push try hg::ssh://hg.mozilla.org/try
|
||||
git config remote.try.push +HEAD:refs/heads/branches/default/tip
|
||||
```
|
||||
* Now update all the remotes. This performs a `git fetch` on all the remotes. Mozilla Central is a _large_ repository. Be prepared for this to take a very long time.
|
||||
|
||||
```bash
|
||||
git remote update
|
||||
```
|
||||
|
||||
All that's left to do now is pick a bug to fix and [submit a patch](contributing-to-mc).
|
|
@ -1,179 +0,0 @@
|
|||
.. -*- Mode: rst; fill-column: 80; -*-
|
||||
===========================
|
||||
Mozilla Central Quick Start
|
||||
===========================
|
||||
|
||||
Table of contents
|
||||
=================
|
||||
|
||||
.. contents:: :local:
|
||||
|
||||
Firefox Developer Git Quick Start Guide
|
||||
=======================================
|
||||
|
||||
Getting setup to as a first time Mozilla contributor is hard. There are
|
||||
plenty of guides out there to help you get started as a contributor, but
|
||||
many of the new contributor guides out of date often more current ones
|
||||
are aimed at more experienced contributors. If you want to review these
|
||||
guides, you can find several linked to from `Contributing to the Mozilla code base <https://developer.mozilla.org/docs/Mozilla/Developer_guide/Introduction>`_
|
||||
on `MDN <https://developer.mozilla.org/>`_.
|
||||
|
||||
This guide will take you through setting up as a contributor to
|
||||
``mozilla-central``, the Firefox main repository, as a git user.
|
||||
|
||||
Setup
|
||||
-----
|
||||
|
||||
The first thing you will need is to install Mercurial as this is the VCS
|
||||
that ``mozilla-central`` uses.
|
||||
|
||||
Mac
|
||||
~~~
|
||||
|
||||
Homebrew
|
||||
^^^^^^^^
|
||||
|
||||
.. code:: bash
|
||||
|
||||
brew install mercurial
|
||||
|
||||
macports
|
||||
^^^^^^^^
|
||||
|
||||
.. code:: bash
|
||||
|
||||
sudo port install mercurial
|
||||
|
||||
Linux
|
||||
~~~~~
|
||||
|
||||
apt
|
||||
^^^
|
||||
|
||||
.. code:: bash
|
||||
|
||||
sudo apt-get install mercurial
|
||||
|
||||
Alternatively you can install `Mercurial directly <https://www.mercurial-scm.org/wiki/Download>`_.
|
||||
|
||||
Check that you have successfully installed Mercurial by running:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
hg --version
|
||||
|
||||
If you are an experienced git user and are unfamiliar with Mercurial,
|
||||
you may want to install ``git-cinnabar``. Cinnabar is a git remote
|
||||
helper that allows you to interact with Mercurial repos using git
|
||||
semantics.
|
||||
|
||||
git-cinnabar
|
||||
------------
|
||||
|
||||
There is a Homebrew install option for ``git-cinnabar``, but this did
|
||||
not work for me, nor did the installer option. Using these tools, when I
|
||||
tried to clone the Mercurial repo it hung and did not complete. I had to
|
||||
do a manual install before I could use ``git-cinnabar`` successfully to
|
||||
download a Mercurial repo. If you would like to try either of these
|
||||
option, however, here they are:
|
||||
|
||||
.. _mac-1:
|
||||
|
||||
Mac
|
||||
~~~
|
||||
|
||||
.. _homebrew-1:
|
||||
|
||||
Homebrew
|
||||
^^^^^^^^
|
||||
|
||||
.. code:: bash
|
||||
|
||||
brew install git-cinnabar
|
||||
|
||||
All Platforms
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
Installer
|
||||
^^^^^^^^^
|
||||
|
||||
.. code:: bash
|
||||
|
||||
git cinnabar download
|
||||
|
||||
Manual installation
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code:: bash
|
||||
|
||||
git clone https://github.com/glandium/git-cinnabar.git && cd git-cinnabar
|
||||
make
|
||||
export PATH="$PATH:/somewhere/git-cinnabar"
|
||||
echo 'export PATH="$PATH:/somewhere/git-cinnabar"' >> ~/.bash_profile
|
||||
git cinnabar download
|
||||
|
||||
``git-cinnabar``\ ’s creator, `glandium <https://glandium.org/>`_, has
|
||||
written a number of posts about setting up for Firefox Development with
|
||||
git. This `post <https://glandium.org/blog/?page_id=3438>`_ is the one
|
||||
that has formed the basis for this walkthrough.
|
||||
|
||||
In synopsis:
|
||||
|
||||
- initialize an empty git repository
|
||||
|
||||
.. code:: bash
|
||||
|
||||
git init gecko && cd gecko
|
||||
|
||||
- Configure git:
|
||||
|
||||
.. code:: bash
|
||||
|
||||
git config fetch.prune true
|
||||
git config push.default upstream
|
||||
|
||||
- Add remotes for your repositories. There are several to choose from,
|
||||
``central``, ``inbound``, ``beta``, ``release`` etc. but in reality,
|
||||
if you plan on using Phabricator, which is Firefox’s preferred patch
|
||||
submission system, you only need to set up ``central``. It might be
|
||||
advisable to have access to ``inbound`` however, if you want to work
|
||||
on a version of Firefox that is queued for release. This guide will
|
||||
be focused on Phabricator.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
git remote add central hg::https://hg.mozilla.org/mozilla-central -t branches/default/tip
|
||||
git remote add inbound hg::https://hg.mozilla.org/integration/mozilla-inbound -t branches/default/tip
|
||||
git remote set-url --push central hg::ssh://hg.mozilla.org/mozilla-central
|
||||
git remote set-url --push inbound hg::ssh://hg.mozilla.org/integration/mozilla-inbound
|
||||
|
||||
- Expose the branch tip to get quick access with some easy names.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
git config remote.central.fetch +refs/heads/branches/default/tip:refs/remotes/central/default
|
||||
git config remote.inbound.fetch +refs/heads/branches/default/tip:refs/remotes/inbound/default
|
||||
|
||||
- Setup a remote for the try server. The try server is an easy way to
|
||||
test a patch without actually checking the patch into the core
|
||||
repository. Your code will go through the same tests as a
|
||||
``mozilla-central`` push, and you’ll be able to download builds if
|
||||
you wish.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
git remote add try hg::https://hg.mozilla.org/try
|
||||
git config remote.try.skipDefaultUpdate true
|
||||
git remote set-url --push try hg::ssh://hg.mozilla.org/try
|
||||
git config remote.try.push +HEAD:refs/heads/branches/default/tip
|
||||
|
||||
- Now update all the remotes. This performs a ``git fetch`` on all the
|
||||
remotes. Mozilla Central is a *large* repository. Be prepared for
|
||||
this to take a very long time.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
git remote update
|
||||
|
||||
All that’s left to do now is pick a bug to fix and `submit a
|
||||
patch <contributing-to-mc>`__.
|
|
@ -0,0 +1,139 @@
|
|||
---
|
||||
layout: default
|
||||
title: Debugging Native Code
|
||||
summary: How to set up native debugging for GeckoView using Android Studio.
|
||||
tags: [GeckoView,Gecko,mozilla,android,WebView,mobile,debugging,native,android studio]
|
||||
nav_exclude: true
|
||||
exclude: true
|
||||
---
|
||||
## Table of contents
|
||||
{: .no_toc .text-delta }
|
||||
|
||||
1. TOC
|
||||
{:toc}
|
||||
|
||||
# Debugging Native Code in Android Studio.
|
||||
If you want to work on the C++ code that powers GeckoView, you will need to be able to perform native debugging inside Android Studio. This article will guide you through how to do that.
|
||||
|
||||
If you need to get set up with GeckoView for the first time, follow the [Quick Start Guide](geckoview-quick-start).
|
||||
|
||||
## Perform a debug build of Gecko.
|
||||
1. Edit your `mozconfig` file and add the following lines. These will ensure that the build includes debug checks and symbols.
|
||||
|
||||
```
|
||||
ac_add_options --enable-debug
|
||||
ac_add_options --with-android-ndk="<path>/.mozbuild/android-ndk-r17b"
|
||||
```
|
||||
2. Ensure that the following lines are commented out in your `mozconfig` if present. `./mach configure` will not allow artifact builds to be enabled when generating a debug build.
|
||||
|
||||
```
|
||||
# ac_add_options --enable-artifact-builds
|
||||
```
|
||||
3. To be absolutely sure that Android Studio will pick up your debug symbols, the first time you perform a debug build it is best to clobber your `MOZ_OBJDIR`. Subsequent builds should not need this step.
|
||||
|
||||
```bash
|
||||
./mach clobber
|
||||
```
|
||||
4. Build as usual. Because this is a debug build, and because you have clobbered your `MOZ_OBJDIR`, this will take a long time. Subsequent builds will be incremental and take less time, so go make yourself a cup of your favourite beverage.
|
||||
|
||||
```bash
|
||||
./mach build
|
||||
```
|
||||
## Set up lldb to find your symbols
|
||||
Edit your `~/.lldbinit` file (or create one if one does not already exist) and add the following lines.
|
||||
|
||||
The first line tells LLDB to enable inline breakpoints - Android Studio will need this if you want to use visual breakpoints.
|
||||
|
||||
The remaining lines tell LLDB where to go to find the symbols for debugging.
|
||||
|
||||
```bash
|
||||
settings set target.inline-breakpoint-strategy always
|
||||
settings append target.exec-search-paths <PATH>/objdir-android-opt/toolkit/library/build
|
||||
settings append target.exec-search-paths <PATH>/objdir-android-opt/mozglue/build
|
||||
```
|
||||
# Set up Android Studio to perform native debugging.
|
||||
|
||||
1. Edit the configuration that you want to debug by clicking `Run -> Edit Configurations...` and selecting the correct configuration from the options on the left hand side of the resulting window.
|
||||
2. Select the `Debugger` tab.
|
||||
3. Select `Dual` from the `Debug type` select box. Dual will allow debugging of both native and Java code in the same session. It is possible to use `Native`, but it will only allow for debugging native code, and it's frequently necessary to break in the Java code that configures Gecko and child processes in order to attach debuggers at the correct times.
|
||||
4. Under `Symbol Directories`, add a new path pointing to `<PATH>/objdir-android-opt/toolkit/library/build`, the same path that you entered into your `.lldbinit` file.
|
||||
5. Select `Apply` and `OK` to close the window.
|
||||
|
||||
# Debug Native code in Android Studio
|
||||
|
||||
1. The first time you are running a debug session for your app, it's best to start from a completely clean build. Click `Build -> Rebuild Project` to clean and rebuild. You can also choose to remove any existing builds from your emulator to be completely sure, but this may not be necessary.
|
||||
2. If using Android Studio visual breakpoints, set your breakpoints in your native code.
|
||||
3. Run the app in debug mode as usual.
|
||||
4. When debugging Fennec or geckoview_example, you will almost immediately hit a breakpoint in `ElfLoader.cpp`. This is expected. If you are not using Android Studio visual breakpoints, you can set your breakpoints here using the lldb console that is available now this breakpoint has been hit. To set a breakpoint, select the app tab (if running Dual, there will also be an `<app> java` tab) from the debug window, and then select the `lldb` console tab. Type the following into the console:
|
||||
|
||||
```lldb
|
||||
b <file>.cpp:<line number>
|
||||
```
|
||||
5. Once your breakpoints have been set, click the continue execution button to move beyond the `ElfLoader` breakpoint and your newly set native breakpoints should be hit. Debug as usual.
|
||||
|
||||
## Attaching debuggers to content and other child processes
|
||||
|
||||
Internally, GeckoView has a multi-process architecture. The main Gecko process lives in the main Android process, but content rendering and some other functions live in child processes. This balances load, ensures certain critical security properties, and allows GeckoView to recover if content processes become unresponsive or crash. However, it's generally delicate to debug child processes because they come and go.
|
||||
|
||||
The general approach is to make the Java code in the child process that you want to debug wait for a Java debugger at startup, and then to connect such a Java debugger manually from the Android Studio UI.
|
||||
|
||||
[Bug 1522318](https://bugzilla.mozilla.org/show_bug.cgi?id=1522318) added environment variables that makes GeckoView wait for Java debuggers to attach, making this debug process more developer-friendly. See [Configuring GeckoView for Automation](../consumer/docs/automation) for instructions on how to set environment variables that configure GeckoView's runtime environment.
|
||||
|
||||
### Making processes wait for a Java debugger
|
||||
|
||||
The following environment variable makes the main (Gecko) process wait for a Java debugger to connect:
|
||||
|
||||
```shell
|
||||
MOZ_DEBUG_WAIT_FOR_JAVA_DEBUGGER=1
|
||||
```
|
||||
|
||||
This is a superset of Android Studio's built-in debugging support so it's not particularly useful (unless you want to attach a different jdwp debugger).
|
||||
|
||||
The following environment variable makes every child process wait for a Java debugger to connect:
|
||||
|
||||
```shell
|
||||
MOZ_DEBUG_CHILD_WAIT_FOR_JAVA_DEBUGGER=
|
||||
```
|
||||
|
||||
Set `MOZ_DEBUG_CHILD_WAIT_FOR_JAVA_DEBUGGER=suffix` in the environment to make child processes with an Android process name ending with `suffix` wait for a Java debugger to connect. For example, the following environment variable makes every child content process wait for a Java debugger to connect:
|
||||
|
||||
```shell
|
||||
MOZ_DEBUG_CHILD_WAIT_FOR_JAVA_DEBUGGER=:tab
|
||||
```
|
||||
|
||||
An easy way to set this is with `./mach run`:
|
||||
|
||||
```shell
|
||||
./mach run --setenv MOZ_DEBUG_CHILD_WAIT_FOR_JAVA_DEBUGGER=:tab
|
||||
```
|
||||
|
||||
### Attaching a Java debugger to a waiting child process
|
||||
|
||||
This is standard: follow the [Android Studio instructions](https://developer.android.com/studio/debug/index.html#attach-debugger). You must attach a Java debugger, so you almost certainly want to attach a `Dual` debugger and you definitely can't attach only a `Native` debugger.
|
||||
|
||||
Determining the correct process to attach to is a little tricky because the mapping from process ID (pid) to process name is not always clear. Gecko content child processes are suffixed `:tab` at this time.
|
||||
|
||||
If you attach `Dual` debuggers to both the main process and a content child process, you will have four (4!) debug tabs to manage in Android Studio, which is awkward. Android Studio doesn't appear to configure attached debuggers in the same way that it configures debuggers connecting to launched Run Configurations, so you may need to manually configure search paths -- i.e., you may need to invoke the contents of your `lldbinit` file in the appropriate `lldb` console by hand, using an invocation like `command source /absolute/path/to/topobjdir/lldbinit`.
|
||||
|
||||
Android Studio also doesn't appear to support targeting breakpoints from the UI (say, from clicking in a gutter) to specific debug tabs, so you may also need to set breakpoints in the appropriate `lldb` console by hand.
|
||||
|
||||
Managing more debug tabs may require different approaches.
|
||||
|
||||
### Using Android Studio on Windows
|
||||
|
||||
You can now use [artifact builds](https://developer.mozilla.org/docs/Mozilla/Developer_guide/Build_Instructions/Artifact_builds) mode on [MozillaBuild environment](https://wiki.mozilla.org/MozillaBuild) even if you are not using WSL. If you want to debug GeckoView using Android Studio on Windows, you have to set an additional environment variable via the Control Panel to run the gradle script. The `mach` command sets these variables automatically, but Android Studio cannot.
|
||||
|
||||
If you install MozillaBuild tools to `C:\mozilla-build` (default installation path), you have to set the `MOZILLABUILD` environment variable to recognize MozillaBuild installation path.
|
||||
|
||||
To set environment variable on Windows 10, open the `Control Panel` from `Windows System`, then select `System and Security` - `System` - `Advanced system settings` - `Environment Variables ...`.
|
||||
|
||||
To set the `MOZILLABUILD` variable, click `New...` in `User variables for`, then `Variable name:` is `MOZILLABUILD` and `Variable value:` is `C:\mozilla-build`.
|
||||
|
||||
You also have to append some tool paths to the `Path` environment variable.
|
||||
|
||||
To append the variables to PATH, double click `Path` in `User Variables for`, then click `New`. And append the following variables to `Path`.
|
||||
|
||||
* `%MOZILLABUILD%\msys\bin`
|
||||
* `%MOZILLABUILD%\bin`
|
||||
|
||||
|
|
@ -1,241 +0,0 @@
|
|||
.. -*- Mode: rst; fill-column: 80; -*-
|
||||
=====================
|
||||
Debugging Native Code
|
||||
=====================
|
||||
|
||||
Table of contents
|
||||
=================
|
||||
|
||||
.. contents:: :local:
|
||||
|
||||
Debugging Native Code in Android Studio.
|
||||
========================================
|
||||
|
||||
If you want to work on the C++ code that powers GeckoView, you will need
|
||||
to be able to perform native debugging inside Android Studio. This
|
||||
article will guide you through how to do that.
|
||||
|
||||
If you need to get set up with GeckoView for the first time, follow the
|
||||
`Quick Start Guide <geckoview-quick-start.html>`_.
|
||||
|
||||
Perform a debug build of Gecko.
|
||||
-------------------------------
|
||||
|
||||
1. Edit your ``mozconfig`` file and add the following lines. These will
|
||||
ensure that the build includes debug checks and symbols.
|
||||
|
||||
.. code:: txt
|
||||
|
||||
ac_add_options --enable-debug
|
||||
ac_add_options --with-android-ndk="<path>/.mozbuild/android-ndk-r17b"
|
||||
|
||||
2. Ensure that the following lines are commented out in your
|
||||
``mozconfig`` if present. ``./mach configure`` will not allow
|
||||
artifact builds to be enabled when generating a debug build.
|
||||
|
||||
.. code:: txt
|
||||
|
||||
# ac_add_options --enable-artifact-builds
|
||||
|
||||
3. To be absolutely sure that Android Studio will pick up your debug
|
||||
symbols, the first time you perform a debug build it is best to
|
||||
clobber your ``MOZ_OBJDIR``. Subsequent builds should not need this
|
||||
step.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
./mach clobber
|
||||
|
||||
4. Build as usual. Because this is a debug build, and because you have
|
||||
clobbered your ``MOZ_OBJDIR``, this will take a long time. Subsequent
|
||||
builds will be incremental and take less time, so go make yourself a
|
||||
cup of your favourite beverage.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
./mach build
|
||||
|
||||
Set up lldb to find your symbols
|
||||
--------------------------------
|
||||
|
||||
Edit your ``~/.lldbinit`` file (or create one if one does not already
|
||||
exist) and add the following lines.
|
||||
|
||||
The first line tells LLDB to enable inline breakpoints - Android Studio
|
||||
will need this if you want to use visual breakpoints.
|
||||
|
||||
The remaining lines tell LLDB where to go to find the symbols for
|
||||
debugging.
|
||||
|
||||
.. code:: bash
|
||||
|
||||
settings set target.inline-breakpoint-strategy always
|
||||
settings append target.exec-search-paths <PATH>/objdir-android-opt/toolkit/library/build
|
||||
settings append target.exec-search-paths <PATH>/objdir-android-opt/mozglue/build
|
||||
|
||||
Set up Android Studio to perform native debugging.
|
||||
==================================================
|
||||
|
||||
1. Edit the configuration that you want to debug by clicking
|
||||
``Run -> Edit Configurations...`` and selecting the correct
|
||||
configuration from the options on the left hand side of the resulting
|
||||
window.
|
||||
2. Select the ``Debugger`` tab.
|
||||
3. Select ``Dual`` from the ``Debug type`` select box. Dual will allow
|
||||
debugging of both native and Java code in the same session. It is
|
||||
possible to use ``Native``, but it will only allow for debugging
|
||||
native code, and it’s frequently necessary to break in the Java code
|
||||
that configures Gecko and child processes in order to attach
|
||||
debuggers at the correct times.
|
||||
4. Under ``Symbol Directories``, add a new path pointing to
|
||||
``<PATH>/objdir-android-opt/toolkit/library/build``, the same path
|
||||
that you entered into your ``.lldbinit`` file.
|
||||
5. Select ``Apply`` and ``OK`` to close the window.
|
||||
|
||||
Debug Native code in Android Studio
|
||||
===================================
|
||||
|
||||
1. The first time you are running a debug session for your app, it’s
|
||||
best to start from a completely clean build. Click
|
||||
``Build -> Rebuild Project`` to clean and rebuild. You can also
|
||||
choose to remove any existing builds from your emulator to be
|
||||
completely sure, but this may not be necessary.
|
||||
2. If using Android Studio visual breakpoints, set your breakpoints in
|
||||
your native code.
|
||||
3. Run the app in debug mode as usual.
|
||||
4. When debugging Fennec or geckoview_example, you will almost
|
||||
immediately hit a breakpoint in ``ElfLoader.cpp``. This is expected.
|
||||
If you are not using Android Studio visual breakpoints, you can set
|
||||
your breakpoints here using the lldb console that is available now
|
||||
this breakpoint has been hit. To set a breakpoint, select the app tab
|
||||
(if running Dual, there will also be an ``<app> java`` tab) from the
|
||||
debug window, and then select the ``lldb`` console tab. Type the
|
||||
following into the console:
|
||||
|
||||
.. code:: lldb
|
||||
|
||||
b <file>.cpp:<line number>
|
||||
|
||||
5. Once your breakpoints have been set, click the continue execution
|
||||
button to move beyond the ``ElfLoader`` breakpoint and your newly set
|
||||
native breakpoints should be hit. Debug as usual.
|
||||
|
||||
Attaching debuggers to content and other child processes
|
||||
--------------------------------------------------------
|
||||
|
||||
Internally, GeckoView has a multi-process architecture. The main Gecko
|
||||
process lives in the main Android process, but content rendering and
|
||||
some other functions live in child processes. This balances load,
|
||||
ensures certain critical security properties, and allows GeckoView to
|
||||
recover if content processes become unresponsive or crash. However, it’s
|
||||
generally delicate to debug child processes because they come and go.
|
||||
|
||||
The general approach is to make the Java code in the child process that
|
||||
you want to debug wait for a Java debugger at startup, and then to
|
||||
connect such a Java debugger manually from the Android Studio UI.
|
||||
|
||||
`Bug 1522318 <https://bugzilla.mozilla.org/show_bug.cgi?id=1522318>`__
|
||||
added environment variables that makes GeckoView wait for Java debuggers
|
||||
to attach, making this debug process more developer-friendly. See
|
||||
`Configuring GeckoView for Automation <../consumer/automation.html>`__
|
||||
for instructions on how to set environment variables that configure
|
||||
GeckoView’s runtime environment.
|
||||
|
||||
Making processes wait for a Java debugger
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The following environment variable makes the main (Gecko) process wait
|
||||
for a Java debugger to connect:
|
||||
|
||||
.. code:: shell
|
||||
|
||||
MOZ_DEBUG_WAIT_FOR_JAVA_DEBUGGER=1
|
||||
|
||||
This is a superset of Android Studio’s built-in debugging support so
|
||||
it’s not particularly useful (unless you want to attach a different jdwp
|
||||
debugger).
|
||||
|
||||
The following environment variable makes every child process wait for a
|
||||
Java debugger to connect:
|
||||
|
||||
.. code:: shell
|
||||
|
||||
MOZ_DEBUG_CHILD_WAIT_FOR_JAVA_DEBUGGER=
|
||||
|
||||
Set ``MOZ_DEBUG_CHILD_WAIT_FOR_JAVA_DEBUGGER=suffix`` in the environment
|
||||
to make child processes with an Android process name ending with
|
||||
``suffix`` wait for a Java debugger to connect. For example, the
|
||||
following environment variable makes every child content process wait
|
||||
for a Java debugger to connect:
|
||||
|
||||
.. code:: shell
|
||||
|
||||
MOZ_DEBUG_CHILD_WAIT_FOR_JAVA_DEBUGGER=:tab
|
||||
|
||||
An easy way to set this is with ``./mach run``:
|
||||
|
||||
.. code:: shell
|
||||
|
||||
./mach run --setenv MOZ_DEBUG_CHILD_WAIT_FOR_JAVA_DEBUGGER=:tab
|
||||
|
||||
Attaching a Java debugger to a waiting child process
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This is standard: follow the `Android Studio instructions <https://developer.android.com/studio/debug/index.html#attach-debugger>`_.
|
||||
You must attach a Java debugger, so you almost certainly want to attach
|
||||
a ``Dual`` debugger and you definitely can’t attach only a ``Native``
|
||||
debugger.
|
||||
|
||||
Determining the correct process to attach to is a little tricky because
|
||||
the mapping from process ID (pid) to process name is not always clear.
|
||||
Gecko content child processes are suffixed ``:tab`` at this time.
|
||||
|
||||
If you attach ``Dual`` debuggers to both the main process and a content
|
||||
child process, you will have four (4!) debug tabs to manage in Android
|
||||
Studio, which is awkward. Android Studio doesn’t appear to configure
|
||||
attached debuggers in the same way that it configures debuggers
|
||||
connecting to launched Run Configurations, so you may need to manually
|
||||
configure search paths – i.e., you may need to invoke the contents of
|
||||
your ``lldbinit`` file in the appropriate ``lldb`` console by hand,
|
||||
using an invocation like
|
||||
``command source /absolute/path/to/topobjdir/lldbinit``.
|
||||
|
||||
Android Studio also doesn’t appear to support targeting breakpoints from
|
||||
the UI (say, from clicking in a gutter) to specific debug tabs, so you
|
||||
may also need to set breakpoints in the appropriate ``lldb`` console by
|
||||
hand.
|
||||
|
||||
Managing more debug tabs may require different approaches.
|
||||
|
||||
Using Android Studio on Windows
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
You can now use `artifact builds <https://developer.mozilla.org/docs/Mozilla/Developer_guide/Build_Instructions/Artifact_builds>`_
|
||||
mode on `MozillaBuild environment <https://wiki.mozilla.org/MozillaBuild>`_ even if you are
|
||||
not using WSL. If you want to debug GeckoView using Android Studio on
|
||||
Windows, you have to set an additional environment variable via the
|
||||
Control Panel to run the gradle script. The ``mach`` command sets these
|
||||
variables automatically, but Android Studio cannot.
|
||||
|
||||
If you install MozillaBuild tools to ``C:\mozilla-build`` (default
|
||||
installation path), you have to set the ``MOZILLABUILD`` environment
|
||||
variable to recognize MozillaBuild installation path.
|
||||
|
||||
To set environment variable on Windows 10, open the ``Control Panel``
|
||||
from ``Windows System``, then select ``System and Security`` -
|
||||
``System`` - ``Advanced system settings`` -
|
||||
``Environment Variables ...``.
|
||||
|
||||
To set the ``MOZILLABUILD`` variable, click ``New...`` in
|
||||
``User variables for``, then ``Variable name:`` is ``MOZILLABUILD`` and
|
||||
``Variable value:`` is ``C:\mozilla-build``.
|
||||
|
||||
You also have to append some tool paths to the ``Path`` environment
|
||||
variable.
|
||||
|
||||
To append the variables to PATH, double click ``Path`` in
|
||||
``User Variables for``, then click ``New``. And append the following
|
||||
variables to ``Path``.
|
||||
|
||||
- ``%MOZILLABUILD%\msys\bin``
|
||||
- ``%MOZILLABUILD%\bin``
|
|
@ -1,14 +1,10 @@
|
|||
.. -*- Mode: rst; fill-column: 80; -*-
|
||||
|
||||
Welcome to GeckoView's documentation!
|
||||
=====================================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:hidden:
|
||||
|
||||
consumer/index
|
||||
contributor/index
|
||||
---
|
||||
layout: default
|
||||
title: Geckoview
|
||||
nav_order: 1
|
||||
summary: GeckoView, a WebView-like component from Mozilla specifically designed for building Android browsers.
|
||||
tags: [GeckoView,Gecko,mozilla,android,WebView,mobile,mozilla-central]
|
||||
---
|
||||
|
||||
Android offers a built-in WebView, which applications can hook into in order to display web pages within the context of their app. However, Android's WebView is not really intended for building browsers, and hence, many advanced Web APIs are disabled. Furthermore, it is also a moving target: different phones might have different versions of WebView, all of which your app has to support.
|
||||
|
||||
|
@ -19,26 +15,23 @@ That is where GeckoView comes in. GeckoView is:
|
|||
- **Self-Contained**: Because GeckoView is a standalone library that you bundle with your application, you can be confident that the code you test is the code that will actually run.
|
||||
- **Standards Compliant**: Like Firefox, GeckoView offers excellent support for modern Web standards.
|
||||
|
||||
=================
|
||||
Using GeckoView
|
||||
=================
|
||||
## Using GeckoView
|
||||
|
||||
* `Quick Start Guide <consumer/geckoview-quick-start.html>`_
|
||||
* `Usage Documentation <consumer/index.html>`_
|
||||
* [Quick Start Guide](https://firefox-source-docs.mozilla.org/mobile/android/geckoview/consumer/docs/geckoview-quick-start.html)
|
||||
* [Usage Documentation](https://firefox-source-docs.mozilla.org/mobile/android/geckoview/consumer/docs/index.html)
|
||||
|
||||
=================
|
||||
API Documentation
|
||||
=================
|
||||
## API Documentation
|
||||
|
||||
* `Changelog <https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/doc-files/CHANGELOG>`_
|
||||
* `API <https://firefox-source-docs.mozilla.org/index.html>`_
|
||||
* [Changelog](https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/doc-files/CHANGELOG)
|
||||
* [API](https://firefox-source-docs.mozilla.org/index.html)
|
||||
|
||||
=================
|
||||
More information
|
||||
=================
|
||||
## More information
|
||||
* [GeckoView Wiki][1]
|
||||
* [GeckoView Source Code][2]
|
||||
* [Raise a bug on GeckoView code][3]
|
||||
* [Raise a documentation bug][4]
|
||||
|
||||
* Talk to us on `Riot <https://chat.mozilla.org/#/room/#geckoview:mozilla.org>`_
|
||||
* `GeckoView Wiki <https://wiki.mozilla.org/Mobile/GeckoView>`_
|
||||
* `GeckoView Source Code <https://searchfox.org/mozilla-central/source/mobile/android/geckoview>`_
|
||||
* `Raise a bug on GeckoView code <https://bugzilla.mozilla.org/enter_bug.cgi?product=GeckoView>`_
|
||||
* `Raise a documentation bug <https://github.com/mozilla/geckoview/issues>`_
|
||||
[1]:https://wiki.mozilla.org/Mobile/GeckoView
|
||||
[2]:https://searchfox.org/mozilla-central/source/mobile/android/geckoview
|
||||
[3]:https://bugzilla.mozilla.org/enter_bug.cgi?product=GeckoView
|
||||
[4]:https://github.com/mozilla/geckoview/issues
|
|
@ -253,6 +253,18 @@ REMOVED/DEPRECATED: Use 'mach lint --linter android-checkstyle'.""")
|
|||
# Copy over user documentation.
|
||||
import mozfile
|
||||
|
||||
# Remove existing geckoview docs and replace with the local copy.
|
||||
# Keep all the files that are git specific and not part of the GV documentation.
|
||||
keep_files = [".git", ".gitignore", "_site", "CODE_OF_CONDUCT.md",
|
||||
"Gemfile.lock", "README.md"]
|
||||
for filename in os.listdir(repo_path):
|
||||
if filename not in keep_files:
|
||||
filepath = mozpath.join(repo_path, filename)
|
||||
mozfile.remove(filepath)
|
||||
|
||||
src_path = mozpath.join(self.topsrcdir, 'mobile', 'android', 'docs', 'geckoview')
|
||||
os.system("rsync -aruz {}/ {}/".format(src_path, repo_path))
|
||||
|
||||
# Extract new javadoc to specified directory inside repo.
|
||||
src_tar = mozpath.join(self.topobjdir, 'gradle', 'build', 'mobile', 'android',
|
||||
'geckoview', 'libs', 'geckoview-javadoc.jar')
|
||||
|
|
Загрузка…
Ссылка в новой задаче