Bug 1413739 - Part 1 - Offer Firefox itself as an Assist App. r=nechen

The technique for setting our icon is just a straight reimplementation
of bug 1210242.

Because of the way the new tab might be opened from within a
processActionViewIntent Runnable, we can't enter editing mode by simply
listening for an ACTION_ASSIST intent from within BrowserApp, as we need to
enter editing mode *after* the correct tab has already been opened and selected
and BrowserApp doesn't get any hint on when that Runnable might have run.

Instead, we introduce a new tab event, so we can trigger editing mode at the
right time via the tab itself.

MozReview-Commit-ID: 8Bvv5TXyhhI

--HG--
extra : rebase_source : 92f6131098e1c2a8e810431aa82e68e7e422cfd1
This commit is contained in:
Jan Henning 2017-12-03 21:16:03 +01:00
parent ba5b0824a2
commit d3f7376545
6 changed files with 64 additions and 11 deletions

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<resources>
<integer name="assist_launch_icon_res">@drawable/icon</integer>
</resources>

View File

@ -13,5 +13,6 @@
<integer name="max_search_suggestions">2</integer>
<integer name="max_saved_suggestions">2</integer>
<integer name="shift_duration_suggestion">500</integer>
<integer name="assist_launch_icon_res">0</integer>
</resources>

View File

@ -142,6 +142,22 @@
<data android:scheme="https" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.ASSIST"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
<!-- Pre Lollipop devices display a generic search icon, if none is
provided here. To use this we need to set the resource to 0.
For Lollipop and later the search launcher icon ist used.
To retrieve the resource value the Bundle.getInt() method is
used, so we use integer resources instead of drawables, because
setting a drawable referenced to 0 results in errors when used
as a real drawable resource somewhere else. -->
<meta-data
android:name="com.android.systemui.action_assist_icon"
android:resource="@integer/assist_launch_icon_res"/>
<!-- For XPI installs from websites and the download manager. -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />

View File

@ -435,7 +435,6 @@ public class BrowserApp extends GeckoApp
case PAGE_SHOW:
tab.loadFavicon();
break;
case UNSELECTED:
// We receive UNSELECTED immediately after the SELECTED listeners run
// so we are ensured that the unselectedTabEditingText has not changed.
@ -444,6 +443,9 @@ public class BrowserApp extends GeckoApp
tab.getEditingState().copyFrom(mLastTabEditingState);
}
break;
case START_EDITING:
enterEditingMode();
break;
}
if (HardwareUtils.isTablet() && msg == TabEvents.SELECTED) {

View File

@ -1411,8 +1411,10 @@ public abstract class GeckoApp extends GeckoActivity
final String passedUri = getIntentURI(intent);
final boolean isExternalURL = passedUri != null;
final boolean isAboutHomeURL = isExternalURL && AboutPages.isAboutHome(passedUri);
final boolean intentHasURL = passedUri != null;
final boolean isAboutHomeURL = intentHasURL && AboutPages.isAboutHome(passedUri);
final boolean isAssistIntent = Intent.ACTION_ASSIST.equals(action);
final boolean needsNewForegroundTab = intentHasURL || isAssistIntent;
// Start migrating as early as possible, can do this in
// parallel with Gecko load.
@ -1438,14 +1440,16 @@ public abstract class GeckoApp extends GeckoActivity
handleSelectTabIntent(intent);
// External URLs and new tab from widget should always be loaded regardless of whether Gecko is
// already running.
} else if (isExternalURL) {
} else if (needsNewForegroundTab) {
// Restore tabs before opening an external URL so that the new tab
// is animated properly.
Tabs.getInstance().notifyListeners(null, Tabs.TabEvents.RESTORED);
processActionViewIntent(new Runnable() {
@Override
public void run() {
if (isAboutHomeURL) {
if (isAssistIntent) {
Tabs.getInstance().addTab(Tabs.LOADURL_START_EDITING | Tabs.LOADURL_EXTERNAL);
} else if (isAboutHomeURL) {
// respect the user preferences for about:home from external intent calls
loadStartupTab(Tabs.LOADURL_NEW_TAB, action);
} else {
@ -1780,6 +1784,8 @@ public abstract class GeckoApp extends GeckoActivity
Tabs.getInstance().loadUrlWithIntentExtras(url, intent, flags);
}
});
} else if (Intent.ACTION_ASSIST.equals(action)) {
Tabs.getInstance().addTab(Tabs.LOADURL_START_EDITING | Tabs.LOADURL_EXTERNAL);
} else if (ACTION_HOMESCREEN_SHORTCUT.equals(action)) {
final GeckoBundle data = new GeckoBundle(2);
data.putString("uri", uri);

View File

@ -84,6 +84,8 @@ public class Tabs implements BundleEventListener {
public static final int LOADURL_EXTERNAL = 1 << 7;
/** Indicates the tab is the first shown after Firefox is hidden and restored. */
public static final int LOADURL_FIRST_AFTER_ACTIVITY_UNHIDDEN = 1 << 8;
/** Indicates that we should enter editing mode after opening the tab. */
public static final int LOADURL_START_EDITING = 1 << 9;
private static final long PERSIST_TABS_AFTER_MILLISECONDS = 1000 * 2;
@ -758,7 +760,8 @@ public class Tabs implements BundleEventListener {
AUDIO_PLAYING_CHANGE,
OPENED_FROM_TABS_TRAY,
MEDIA_PLAYING_CHANGE,
MEDIA_PLAYING_RESUME
MEDIA_PLAYING_RESUME,
START_EDITING,
}
public void notifyListeners(Tab tab, TabEvents msg) {
@ -987,6 +990,7 @@ public class Tabs implements BundleEventListener {
boolean desktopMode = (flags & LOADURL_DESKTOP) != 0;
boolean external = (flags & LOADURL_EXTERNAL) != 0;
final boolean isFirstShownAfterActivityUnhidden = (flags & LOADURL_FIRST_AFTER_ACTIVITY_UNHIDDEN) != 0;
final boolean startEditing = (flags & LOADURL_START_EDITING) != 0;
data.putString("url", url);
data.putString("engine", searchEngine);
@ -1065,26 +1069,40 @@ public class Tabs implements BundleEventListener {
selectTab(tabToSelect.getId());
}
if (startEditing) {
notifyListeners(tabToSelect, TabEvents.START_EDITING);
}
// Load favicon instantly for about:home page because it's already cached
if (AboutPages.isBuiltinIconPage(url)) {
tabToSelect.loadFavicon();
}
return tabToSelect;
}
/**
* Opens a new tab and loads either about:home or, if PREFS_HOMEPAGE_FOR_EVERY_NEW_TAB is set,
* the user's homepage.
* Opens a new tab and loads a page according to the user's preferences (by default about:home).
*/
@RobocopTarget
public Tab addTab() {
return loadUrl(getHomepageForNewTab(mAppContext), Tabs.LOADURL_NEW_TAB);
return addTab(Tabs.LOADURL_NONE);
}
/**
* Opens a new tab and loads a page according to the user's preferences (by default about:home).
*/
public Tab addPrivateTab() {
return loadUrl(getHomepageForNewTab(mAppContext), Tabs.LOADURL_NEW_TAB | Tabs.LOADURL_PRIVATE);
return addTab(Tabs.LOADURL_PRIVATE);
}
/**
* Opens a new tab and loads a page according to the user's preferences (by default about:home).
*
* @param flags additional flags used when opening the tab
*/
public Tab addTab(int flags) {
return loadUrl(getHomepageForNewTab(mAppContext), flags | Tabs.LOADURL_NEW_TAB);
}
/**