diff --git a/app/metrics.yaml b/app/metrics.yaml index 6e355f0a096f..6cf6558a0281 100644 --- a/app/metrics.yaml +++ b/app/metrics.yaml @@ -111,16 +111,18 @@ events: preference_key: description: "The preference key for the switch preference the user toggled. We currently track: show_search_suggestions, remote_debugging, telemetry, tracking_protection, search_bookmarks, - search_browsing_history, show_clipboard_suggestions, and show_search_shortcuts" + search_browsing_history, show_clipboard_suggestions, show_search_shortcuts, and open_links_in_a_private_tab" enabled: description: "Whether or not the preference is *now* enabled" bugs: - https://github.com/mozilla-mobile/fenix/issue/975 - https://github.com/mozilla-mobile/fenix/issue/5094 + - https://github.com/mozilla-mobile/fenix/issues/5737 data_reviews: - https://github.com/mozilla-mobile/fenix/pull/1896 - https://github.com/mozilla-mobile/fenix/pull/5704 - https://github.com/mozilla-mobile/fenix/pull/5886 + - https://github.com/mozilla-mobile/fenix/pull/5975 notification_emails: - fenix-core@mozilla.com expires: "2020-03-01" @@ -138,6 +140,20 @@ events: notification_emails: - fenix-core@mozilla.com expires: "2020-03-01" + opened_link: + type: event + description: > + A user opened a link with Fenix + extra_keys: + mode: + description: "The mode the link was opened in. Either 'PRIVATE' or 'NORMAL'" + bugs: + - https://github.com/mozilla-mobile/fenix/issue/5737 + data_reviews: + - https://github.com/mozilla-mobile/fenix/pull/5975 + notification_emails: + - fenix-core@mozilla.com + expires: "2020-03-01" search_shortcuts: selected: diff --git a/app/src/main/java/org/mozilla/fenix/IntentReceiverActivity.kt b/app/src/main/java/org/mozilla/fenix/IntentReceiverActivity.kt index f51053432fcc..27b2d4b75346 100644 --- a/app/src/main/java/org/mozilla/fenix/IntentReceiverActivity.kt +++ b/app/src/main/java/org/mozilla/fenix/IntentReceiverActivity.kt @@ -13,6 +13,7 @@ import kotlinx.coroutines.MainScope import kotlinx.coroutines.launch import mozilla.components.feature.intent.processing.TabIntentProcessor import mozilla.components.support.utils.Browsers +import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.customtabs.ExternalAppBrowserActivity import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.settings @@ -47,14 +48,26 @@ class IntentReceiverActivity : Activity() { Which only appears if the user doesn't have a default set. */ if (didLaunchPrivateLink && Browsers.all(this).isDefaultBrowser) { this.settings().openLinksInAPrivateTab = true + components.analytics.metrics.track(Event.PreferenceToggled( + preferenceKey = getString(R.string.pref_key_open_links_in_a_private_tab), + enabled = true, + context = applicationContext + )) } else if (!Browsers.all(this).isDefaultBrowser) { /* If the user has unset us as the default browser, unset openLinksInAPrivateTab */ this.settings().openLinksInAPrivateTab = false + components.analytics.metrics.track(Event.PreferenceToggled( + preferenceKey = getString(R.string.pref_key_open_links_in_a_private_tab), + enabled = false, + context = applicationContext + )) } val tabIntentProcessor = if (settings().openLinksInAPrivateTab || didLaunchPrivateLink) { + components.analytics.metrics.track(Event.OpenedLink(Event.OpenedLink.Mode.PRIVATE)) components.intentProcessors.privateIntentProcessor } else { + components.analytics.metrics.track(Event.OpenedLink(Event.OpenedLink.Mode.NORMAL)) components.intentProcessors.intentProcessor } diff --git a/app/src/main/java/org/mozilla/fenix/components/metrics/GleanMetricsService.kt b/app/src/main/java/org/mozilla/fenix/components/metrics/GleanMetricsService.kt index 7629699a3cf3..3c0f10f04b7b 100644 --- a/app/src/main/java/org/mozilla/fenix/components/metrics/GleanMetricsService.kt +++ b/app/src/main/java/org/mozilla/fenix/components/metrics/GleanMetricsService.kt @@ -416,6 +416,10 @@ private val Event.wrapper: EventWrapper<*>? { TrackingProtection.etpSettingChanged.record(it) }, { TrackingProtection.etpSettingChangedKeys.valueOf(it) } ) + is Event.OpenedLink -> EventWrapper( + { Events.openedLink.record(it) }, + { Events.openedLinkKeys.valueOf(it) } + ) // Don't record other events in Glean: is Event.AddBookmark -> null is Event.OpenedBookmark -> null diff --git a/app/src/main/java/org/mozilla/fenix/components/metrics/Metrics.kt b/app/src/main/java/org/mozilla/fenix/components/metrics/Metrics.kt index d1d474de3a81..92cd478c3e4d 100644 --- a/app/src/main/java/org/mozilla/fenix/components/metrics/Metrics.kt +++ b/app/src/main/java/org/mozilla/fenix/components/metrics/Metrics.kt @@ -138,7 +138,8 @@ sealed class Event { context.getString(R.string.pref_key_search_bookmarks), context.getString(R.string.pref_key_search_browsing_history), context.getString(R.string.pref_key_show_clipboard_suggestions), - context.getString(R.string.pref_key_show_search_shortcuts) + context.getString(R.string.pref_key_show_search_shortcuts), + context.getString(R.string.pref_key_open_links_in_a_private_tab) ) override val extras: Map? @@ -153,6 +154,12 @@ sealed class Event { } } + data class OpenedLink(val mode: Mode) : Event() { + enum class Mode { NORMAL, PRIVATE } + override val extras: Map? + get() = hashMapOf(Events.openedLinkKeys.mode to mode.name) + } + data class TrackingProtectionSettingChanged(val setting: Setting) : Event() { enum class Setting { STRICT, STANDARD } override val extras: Map? diff --git a/app/src/main/java/org/mozilla/fenix/customtabs/CustomTabToolbarMenu.kt b/app/src/main/java/org/mozilla/fenix/customtabs/CustomTabToolbarMenu.kt index b40247c7ef99..a67263889947 100644 --- a/app/src/main/java/org/mozilla/fenix/customtabs/CustomTabToolbarMenu.kt +++ b/app/src/main/java/org/mozilla/fenix/customtabs/CustomTabToolbarMenu.kt @@ -14,8 +14,8 @@ import mozilla.components.browser.menu.item.SimpleBrowserMenuItem import mozilla.components.browser.session.Session import mozilla.components.browser.session.SessionManager import org.mozilla.fenix.R -import org.mozilla.fenix.theme.ThemeManager import org.mozilla.fenix.components.toolbar.ToolbarMenu +import org.mozilla.fenix.theme.ThemeManager class CustomTabToolbarMenu( private val context: Context, @@ -148,7 +148,7 @@ class CustomTabToolbarMenu( SimpleBrowserMenuItem( { val appName = context.getString(R.string.app_name) - context.getString(R.string.browser_menu_powered_by, appName).toUpperCase() + context.getString(R.string.browser_menu_powered_by2, appName).toUpperCase() }(), ToolbarMenu.CAPTION_TEXT_SIZE, ThemeManager.resolveAttribute(R.attr.primaryText, context) diff --git a/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserFragment.kt b/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserFragment.kt index 6d2c4e2c6f7d..a883209b80aa 100644 --- a/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/customtabs/ExternalAppBrowserFragment.kt @@ -42,6 +42,7 @@ class ExternalAppBrowserFragment : BaseBrowserFragment(), BackHandler { private val customTabsIntegration = ViewBoundFeatureWrapper() private val hideToolbarFeature = ViewBoundFeatureWrapper() + @Suppress("LongMethod") override fun initializeUI(view: View): Session? { return super.initializeUI(view)?.also { val activity = requireActivity() @@ -95,6 +96,14 @@ class ExternalAppBrowserFragment : BaseBrowserFragment(), BackHandler { manifest ) ) + } else { + viewLifecycleOwner.lifecycle.addObserver( + PoweredByNotification( + activity.applicationContext, + requireComponents.core.store, + customTabSessionId + ) + ) } } diff --git a/app/src/main/java/org/mozilla/fenix/customtabs/PoweredByNotification.kt b/app/src/main/java/org/mozilla/fenix/customtabs/PoweredByNotification.kt new file mode 100644 index 000000000000..7a79fe61fb2a --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/customtabs/PoweredByNotification.kt @@ -0,0 +1,96 @@ +/* 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/. */ + +package org.mozilla.fenix.customtabs + +import android.app.Notification +import android.app.NotificationChannel +import android.app.NotificationManager +import android.content.Context +import android.os.Build +import android.os.Build.VERSION.SDK_INT +import androidx.core.app.NotificationCompat +import androidx.core.app.NotificationCompat.BADGE_ICON_NONE +import androidx.core.app.NotificationManagerCompat +import androidx.core.content.ContextCompat +import androidx.core.content.getSystemService +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleObserver +import androidx.lifecycle.OnLifecycleEvent +import mozilla.components.browser.state.selector.findCustomTab +import mozilla.components.browser.state.state.ExternalAppType +import mozilla.components.browser.state.store.BrowserStore +import mozilla.components.support.base.ids.cancel +import mozilla.components.support.base.ids.notify +import org.mozilla.fenix.R + +/** + * Displays a "Powered by Firefox Preview" notification when a Trusted Web Activity is running. + */ +class PoweredByNotification( + private val applicationContext: Context, + private val store: BrowserStore, + private val customTabId: String +) : LifecycleObserver { + + @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) + fun onResume() { + if (store.state.findCustomTab(customTabId)?.config?.externalAppType === ExternalAppType.TRUSTED_WEB_ACTIVITY) { + NotificationManagerCompat.from(applicationContext) + .notify(applicationContext, NOTIFICATION_TAG, buildNotification()) + } + } + + @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) + fun onPause() { + NotificationManagerCompat.from(applicationContext) + .cancel(applicationContext, NOTIFICATION_TAG) + } + + /** + * Build the notification with site controls to be displayed while the web app is active. + */ + private fun buildNotification(): Notification { + val channelId = ensureChannelExists() + + with(applicationContext) { + val appName = getString(R.string.app_name) + return NotificationCompat.Builder(this, channelId) + .setSmallIcon(R.drawable.ic_status_logo) + .setContentTitle(getString(R.string.browser_menu_powered_by2, appName)) + .setBadgeIconType(BADGE_ICON_NONE) + .setColor(ContextCompat.getColor(this, R.color.primary_text_light_theme)) + .setPriority(NotificationCompat.PRIORITY_MIN) + .setShowWhen(false) + .setOngoing(true) + .build() + } + } + + /** + * Make sure a notification channel for the powered by notifications exists. + * + * Returns the channel id to be used for notifications. + */ + private fun ensureChannelExists(): String { + if (SDK_INT >= Build.VERSION_CODES.O) { + val notificationManager: NotificationManager = applicationContext.getSystemService()!! + + val channel = NotificationChannel( + NOTIFICATION_CHANNEL_ID, + applicationContext.getString(R.string.mozac_feature_pwa_site_controls_notification_channel), + NotificationManager.IMPORTANCE_MIN + ) + + notificationManager.createNotificationChannel(channel) + } + + return NOTIFICATION_CHANNEL_ID + } + + companion object { + private const val NOTIFICATION_CHANNEL_ID = "Powered By" + private const val NOTIFICATION_TAG = "PoweredBy" + } +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 91e9f658dea0..c876e757db09 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -91,6 +91,9 @@ POWERED BY %1$s + + Powered by %1$s @@ -639,6 +642,8 @@ Open Delete and Open + + Powered By Collection deleted diff --git a/docs/metrics.md b/docs/metrics.md index 6ac4a469d184..2ab0c76920b2 100644 --- a/docs/metrics.md +++ b/docs/metrics.md @@ -76,8 +76,9 @@ The following metrics are added to the ping: | events.app_opened |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened the app |[1](https://github.com/mozilla-mobile/fenix/pull/1067#issuecomment-474598673)|
  • source: The method used to open Fenix. Possible values are: `app_icon`, `custom_tab` or `link`
|2020-03-01 | | events.browser_menu_action |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A browser menu item was tapped |[1](https://github.com/mozilla-mobile/fenix/pull/1214#issue-264756708), [2](https://github.com/mozilla-mobile/fenix/pull/5098#issuecomment-529658996)|
  • item: A string containing the name of the item the user tapped. These items include: Settings, Library, Help, Desktop Site toggle on/off, Find in Page, New Tab, Private Tab, Share, Report Site Issue, Back/Forward button, Reload Button, Quit
|2020-03-01 | | events.entered_url |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user entered a url |[1](https://github.com/mozilla-mobile/fenix/pull/1067#issuecomment-474598673)|
  • autocomplete: A boolean that tells us whether the URL was autofilled by an Autocomplete suggestion
|2020-03-01 | +| events.opened_link |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened a link with Fenix |[1](https://github.com/mozilla-mobile/fenix/pull/5975)|
  • mode: The mode the link was opened in. Either 'PRIVATE' or 'NORMAL'
|2020-03-01 | | events.performed_search |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user performed a search |[1](https://github.com/mozilla-mobile/fenix/pull/1067#issuecomment-474598673), [2](https://github.com/mozilla-mobile/fenix/pull/1677)|
  • source: A string that tells us how the user performed the search. Possible values are: * default.action * default.suggestion * shortcut.action * shortcut.suggestion
|2020-03-01 | -| events.preference_toggled |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user toggled a preference switch in settings |[1](https://github.com/mozilla-mobile/fenix/pull/1896), [2](https://github.com/mozilla-mobile/fenix/pull/5704), [3](https://github.com/mozilla-mobile/fenix/pull/5886)|
  • enabled: Whether or not the preference is *now* enabled
  • preference_key: The preference key for the switch preference the user toggled. We currently track: show_search_suggestions, remote_debugging, telemetry, tracking_protection, search_bookmarks, search_browsing_history, show_clipboard_suggestions, and show_search_shortcuts
|2020-03-01 | +| events.preference_toggled |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user toggled a preference switch in settings |[1](https://github.com/mozilla-mobile/fenix/pull/1896), [2](https://github.com/mozilla-mobile/fenix/pull/5704), [3](https://github.com/mozilla-mobile/fenix/pull/5886), [4](https://github.com/mozilla-mobile/fenix/pull/5975)|
  • enabled: Whether or not the preference is *now* enabled
  • preference_key: The preference key for the switch preference the user toggled. We currently track: show_search_suggestions, remote_debugging, telemetry, tracking_protection, search_bookmarks, search_browsing_history, show_clipboard_suggestions, show_search_shortcuts, and open_links_in_a_private_tab
|2020-03-01 | | events.search_bar_tapped |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user tapped the search bar |[1](https://github.com/mozilla-mobile/fenix/pull/1067#issuecomment-474598673)|
  • source: The view the user was on when they initiated the search (For example: `Home` or `Browser`)
|2020-03-01 | | events.whats_new_tapped |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user opened the "what's new" page button |[1](https://github.com/mozilla-mobile/fenix/pull/5090)|
  • source: The location from which the user selected the what's new button. Either 'about' or 'home'
|2020-03-01 | | find_in_page.closed |[event](https://mozilla.github.io/glean/book/user/metrics/event.html) |A user closed the find in page UI |[1](https://github.com/mozilla-mobile/fenix/pull/1344#issuecomment-479285010)||2020-03-01 |