Bug 1393672 - Show PWA onboarding and confrim prompt r=jwu
authorNevin Chen(:nechen) <cnevinchen@gmail.com>
Tue, 26 Sep 2017 15:52:36 +0800
changeset 439511 385f9bbb4fd815828556ec0b99676c69f00c163e
parent 439510 b38a9374dabafc411db39a01ef050acf3120b7c5
child 439512 dfb2cb2683f15165e85d35bbcbccc6160c4f7b9e
push id1618
push userCallek@gmail.com
push dateThu, 11 Jan 2018 17:45:48 +0000
treeherdermozilla-release@882ca853e05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwu
bugs1393672
milestone58.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1393672 - Show PWA onboarding and confrim prompt r=jwu MozReview-Commit-ID: Kzih56Om7NO
mobile/android/app/src/main/res/drawable/pwa_cancel_button.xml
mobile/android/app/src/main/res/drawable/pwa_confirm_button.xml
mobile/android/app/src/main/res/drawable/pwa_confirm_button_normal.xml
mobile/android/app/src/main/res/drawable/pwa_confirm_button_pressed.xml
mobile/android/app/src/main/res/layout/pwa_confirm.xml
mobile/android/app/src/main/res/layout/pwa_onboarding.xml
mobile/android/app/src/main/res/layout/tab_prompt_input.xml
mobile/android/app/src/photon/res/drawable-xhdpi/add_to_homescreen.png
mobile/android/app/src/photon/res/drawable-xxhdpi/add_to_homescreen.png
mobile/android/app/src/photon/res/drawable-xxxhdpi/add_to_homescreen.png
mobile/android/app/src/photon/res/drawable/pwa_popup.png
mobile/android/app/src/photon/res/values-large/dimens.xml
mobile/android/app/src/photon/res/values-large/styles.xml
mobile/android/app/src/photon/res/values-v17/styles.xml
mobile/android/app/src/photon/res/values/colors.xml
mobile/android/app/src/photon/res/values/dimens.xml
mobile/android/app/src/photon/res/values/styles.xml
mobile/android/base/java/org/mozilla/gecko/Tab.java
mobile/android/base/java/org/mozilla/gecko/toolbar/PageActionLayout.java
mobile/android/base/java/org/mozilla/gecko/toolbar/PwaConfirm.java
mobile/android/base/java/org/mozilla/gecko/toolbar/PwaOnboarding.java
mobile/android/base/java/org/mozilla/gecko/util/UnusedResourcesUtil.java
mobile/android/base/locales/en-US/android_strings.dtd
mobile/android/base/moz.build
mobile/android/base/strings.xml.in
new file mode 100644
--- /dev/null
+++ b/mobile/android/app/src/main/res/drawable/pwa_cancel_button.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?><!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <!-- pressed state -->
+    <item android:drawable="@color/pwa_cancel_btn_press" android:state_pressed="true" />
+    <!-- normal mode -->
+    <item android:drawable="@color/pwa_cancel_btn" />
+
+</selector>
new file mode 100644
--- /dev/null
+++ b/mobile/android/app/src/main/res/drawable/pwa_confirm_button.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?><!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <!-- pressed state -->
+    <item android:drawable="@drawable/pwa_confirm_button_pressed" android:state_pressed="true" />
+    <!-- normal mode -->
+    <item android:drawable="@drawable/pwa_confirm_button_normal" />
+
+</selector>
new file mode 100644
--- /dev/null
+++ b/mobile/android/app/src/main/res/drawable/pwa_confirm_button_normal.xml
@@ -0,0 +1,11 @@
+<?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/. -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <!--  Gradient Bg for listrow -->
+    <gradient
+        android:angle="45"
+        android:endColor="#0A84FF"
+        android:startColor="#00CBD7" />
+</shape>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/mobile/android/app/src/main/res/drawable/pwa_confirm_button_pressed.xml
@@ -0,0 +1,11 @@
+<?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/. -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <!--  Gradient Bg for listrow -->
+    <gradient
+        android:angle="45"
+        android:endColor="#0060DF"
+        android:startColor="#008EA4" />
+</shape>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/mobile/android/app/src/main/res/layout/pwa_confirm.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="utf-8"?>
+<org.mozilla.gecko.toolbar.PwaConfirm xmlns:android="http://schemas.android.com/apk/res/android"
+                                      xmlns:tools="http://schemas.android.com/tools"
+                                      android:id="@+id/pwa_confirm_root"
+                                      android:layout_width="match_parent"
+                                      android:layout_height="match_parent"
+                                      android:layout_marginTop="@dimen/browser_toolbar_height_flipper"
+                                      android:background="@color/dark_transparent_overlay"
+                                      android:clickable="true">
+
+
+    <RelativeLayout
+        style="@style/PwaConfirm"
+        android:layout_height="wrap_content"
+        android:layout_centerHorizontal="true"
+        android:layout_marginTop="@dimen/tablet_tab_strip_height_pwa"
+        android:background="@color/photon_browser_toolbar_bg"
+        android:clickable="true"
+        android:elevation="15dp">
+
+        <android.support.v7.widget.CardView
+            xmlns:app="http://schemas.android.com/apk/res-auto"
+
+            android:id="@+id/pwa_confirm_icon_wrap"
+            android:layout_width="50dp"
+            android:layout_height="50dp"
+            android:layout_margin="20dp"
+            app:cardCornerRadius="3dp">
+
+            <ImageView
+                android:id="@+id/pwa_confirm_icon"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                tools:background="#f0f"/>
+
+        </android.support.v7.widget.CardView>
+
+        <TextView
+            android:id="@+id/pwa_confirm_title"
+            style="@style/PwaConfirm.Title"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_alignTop="@+id/pwa_confirm_icon_wrap"
+            android:ellipsize="end"
+            android:maxLines="2"
+            android:textColor="#333333"
+            android:textSize="18sp"
+            android:textStyle="bold"
+            tools:text="Mozilla title can grow to two lines... do"/>
+
+
+        <ImageButton
+            android:id="@+id/pwa_confirm_cancel"
+            style="@style/PwaConfirm.Cancel"
+            android:layout_width="48dp"
+            android:layout_height="48dp"
+            android:layout_alignParentTop="true"
+            android:background="@drawable/pwa_cancel_button"
+            android:scaleType="center"
+            android:src="@drawable/ic_cancel_nm"/>
+
+        <Button
+            android:id="@+id/pwa_confirm_action"
+            android:layout_width="match_parent"
+            android:layout_height="69dp"
+            android:layout_below="@+id/pwa_confirm_url"
+            android:layout_marginTop="20dp"
+            android:background="@drawable/pwa_confirm_button"
+            android:gravity="center"
+            android:text="@string/pwa_add_to_launcher_confirm"
+            android:textAllCaps="true"
+            android:textColor="#fff"
+            android:textStyle="bold"/>
+
+        <TextView
+            android:id="@+id/pwa_confirm_url"
+            style="@style/PwaConfirm.Url"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_below="@+id/pwa_confirm_title"
+            android:ellipsize="end"
+            android:maxLines="1"
+            android:textColor="@color/ob_subtitle"
+            android:textSize="13sp"
+            tools:text="http://www.mozilla.org/12345678911123"/>
+    </RelativeLayout>
+
+</org.mozilla.gecko.toolbar.PwaConfirm>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/mobile/android/app/src/main/res/layout/pwa_onboarding.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<org.mozilla.gecko.toolbar.PwaOnboarding xmlns:android="http://schemas.android.com/apk/res/android"
+                                         xmlns:app="http://schemas.android.com/apk/res-auto"
+                                         android:id="@+id/pwa_onboarding_root"
+                                         android:layout_width="match_parent"
+                                         android:layout_height="match_parent"
+                                         android:background="@color/dark_transparent_overlay"
+                                         android:clickable="true"
+                                         android:gravity="center"
+                                         android:orientation="vertical"
+                                         android:padding="20dp">
+
+    <android.support.v7.widget.CardView
+        android:layout_width="290dp"
+        android:layout_height="wrap_content"
+        android:layout_centerHorizontal="true"
+        android:layout_centerVertical="true"
+        android:layout_gravity="center"
+        app:cardCornerRadius="5dp">
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:orientation="vertical">
+
+            <ScrollView
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_margin="5dp"
+                android:layout_weight="1">
+
+                <LinearLayout
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:background="#fff"
+                    android:clickable="true"
+                    android:orientation="vertical">
+
+
+                    <ImageView
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:layout_margin="10dp"
+                        android:src="@drawable/pwa_popup"/>
+
+
+                    <TextView
+                        android:id="@+id/pwa_onboarding_sumo"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:layout_marginBottom="30dp"
+                        android:layout_marginEnd="15dp"
+                        android:layout_marginStart="15dp"
+                        android:layout_marginTop="10dp"
+                        android:lineSpacingExtra="1.4dp"
+                        android:text="@string/pwa_onboarding_sumo"
+                        android:textColor="#737373"
+                        android:textSize="16sp"/>
+                </LinearLayout>
+            </ScrollView>
+
+
+            <View
+                android:layout_width="match_parent"
+                android:layout_height="1dp"
+                android:background="#e5e5e5"/>
+
+            <TextView
+                android:id="@+id/pwa_onboarding_dismiss"
+                android:layout_width="match_parent"
+                android:layout_height="50dp"
+                android:gravity="center"
+                android:text="@string/pwa_continue_to_website"
+                android:textAllCaps="true"
+                android:textColor="@color/photon_highlight"
+                android:textStyle="bold"/>
+        </LinearLayout>
+    </android.support.v7.widget.CardView>
+
+</org.mozilla.gecko.toolbar.PwaOnboarding>
\ No newline at end of file
--- a/mobile/android/app/src/main/res/layout/tab_prompt_input.xml
+++ b/mobile/android/app/src/main/res/layout/tab_prompt_input.xml
@@ -6,27 +6,25 @@
 <TabHost xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@android:id/tabhost"
     android:layout_width="match_parent"
     android:layout_height="match_parent" >
 
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:orientation="vertical"
-        android:minHeight="100dp">
+        android:minHeight="100dp"
+        android:orientation="vertical">
 
         <TabWidget
             android:id="@android:id/tabs"
             style="@style/TabInput.TabWidget"
             android:layout_width="match_parent"
-            android:layout_height="wrap_content" >
-        </TabWidget>
+            android:layout_height="wrap_content"></TabWidget>
 
         <FrameLayout
             android:id="@android:id/tabcontent"
             android:layout_width="match_parent"
-            android:layout_height="match_parent" >
-        </FrameLayout>
+            android:layout_height="match_parent"></FrameLayout>
 
     </LinearLayout>
 
 </TabHost>
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..1216be3d40ca683ebfcdc0a21ffc46558a4d7884
GIT binary patch
literal 2156
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
BvT*<a
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..13ad692357e4e405340afae10efcf20be7e2ef0d
GIT binary patch
literal 2904
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
V-B4=|DVx__+XF{zs;&K#{|(uHB}4!K
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3283ffdbdea3f68d4bc334743898f62673c4ac81
GIT binary patch
literal 3260
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
RhW>S>Ff+2kmYuv5{x3?Y;luy{
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..ba020fc277e0ed17b87e1099e0d8fb82ce3b1c75
GIT binary patch
literal 8745
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
PPRtc$)nN6~7UBN^1pU+-
--- a/mobile/android/app/src/photon/res/values-large/dimens.xml
+++ b/mobile/android/app/src/photon/res/values-large/dimens.xml
@@ -38,9 +38,12 @@
 
     <dimen name="tab_panel_grid_hpadding_autofit">30dp</dimen>
     <dimen name="tab_panel_grid_vpadding_autofit">30dp</dimen>
     <dimen name="tab_panel_grid_item_hpadding_autofit">20dp</dimen>
     <dimen name="tab_panel_grid_item_vpadding_autofit">8dp</dimen>
 
     <!-- PageActionButtons dimensions -->
     <dimen name="page_action_button_width">@dimen/browser_toolbar_icon_width</dimen>
+
+    <dimen name="tablet_tab_strip_height_pwa">48dp</dimen>
+
 </resources>
--- a/mobile/android/app/src/photon/res/values-large/styles.xml
+++ b/mobile/android/app/src/photon/res/values-large/styles.xml
@@ -208,17 +208,23 @@
 
     <style name="UrlBar.SiteIdentity" parent="UrlBar.V15.SiteIdentity" />
 
     <style name="UrlBar.V15.SiteIdentity" parent="UrlBar.Base.SiteIdentity">
         <item name="android:paddingLeft">3dp</item>
         <item name="android:paddingRight">@dimen/browser_toolbar_site_security_margin_end</item>
     </style>
 
+
     <style name="TabsTray.AddTab" parent="TabsTray.V15.AddTab"/>
     <style name="TabsTray.V15.AddTab" parent="TabsTray.Base.AddTab"/>
 
     <style name="TabsTray.Menu" parent="TabsTray.V15.Menu"/>
     <style name="TabsTray.V15.Menu" parent="TabsTray.Base.Menu">
         <item name="android:layout_marginRight">6dp</item>
     </style>
 
+    <style name="PwaConfirm">
+        <item name="android:layout_width">640dp</item>
+
+    </style>
+
 </resources>
--- a/mobile/android/app/src/photon/res/values-v17/styles.xml
+++ b/mobile/android/app/src/photon/res/values-v17/styles.xml
@@ -110,9 +110,22 @@
     </style>
 
     <style name="TabStrip.Title" parent="TabStrip.V17.Title"/>
     <style name="TabStrip.V17.Title" parent="TabStrip.Base">
         <item name="android:layout_toEndOf">@id/favicon</item>
         <item name="android:layout_toStartOf">@id/close</item>
     </style>
 
+    <style name="PwaConfirm.Title">
+        <item name="android:layout_toEndOf">@id/pwa_confirm_icon_wrap</item>
+        <item name="android:layout_toStartOf">@id/pwa_confirm_cancel</item>
+    </style>
+
+    <style name="PwaConfirm.Cancel">
+        <item name="android:layout_alignParentEnd">true</item>
+    </style>
+
+    <style name="PwaConfirm.Url">
+        <item name="android:layout_alignStart">@+id/pwa_confirm_title</item>
+    </style>
+
 </resources>
--- a/mobile/android/app/src/photon/res/values/colors.xml
+++ b/mobile/android/app/src/photon/res/values/colors.xml
@@ -262,9 +262,15 @@
     <color name="activity_stream_subtitle">#FF919191</color>
     <color name="activity_stream_icon">#FF919191</color>
 
     <color name="tablet_tab_strip_divider_color">#737373</color>
     <color name="tablet_tab_strip_indicator">#0060DF</color>
     <color name="tablet_tab_strip_indicator_private">#8000D7</color>
 
     <color name="bookmark_folder_bg_color">#FCFCFC</color>
+
+    <!-- PWA -->
+    <color name="pwa_cancel_btn_press">#ededf0</color>
+    <color name="pwa_cancel_btn">@android:color/transparent</color>
+
+
 </resources>
--- a/mobile/android/app/src/photon/res/values/dimens.xml
+++ b/mobile/android/app/src/photon/res/values/dimens.xml
@@ -41,16 +41,17 @@
     <!-- If you update one of these values, update the others. -->
     <dimen name="tablet_nav_button_width">48dp</dimen>
     <dimen name="tablet_nav_button_width_half">21dp</dimen>
     <dimen name="tablet_nav_button_width_plus_half">36dp</dimen>
 
     <dimen name="tablet_fwd_button_padding_start">4dp</dimen>
     <dimen name="tablet_fwd_button_padding_end">4dp</dimen>
 
+    <dimen name="tablet_tab_strip_height_pwa">0dp</dimen>
     <dimen name="tablet_tab_strip_height">48dp</dimen>
     <dimen name="tablet_tab_strip_item_width">178dp</dimen>
     <dimen name="tablet_tab_strip_item_height">40dp</dimen>
     <dimen name="tablet_tab_strip_fading_edge_size">15dp</dimen>
     <dimen name="tablet_tab_strip_item_margin">0dp</dimen>
     <dimen name="tablet_tab_strip_divider_width">1dp</dimen>
     <dimen name="tablet_tab_strip_divider_height">30dp</dimen>
     <dimen name="tablet_tab_strip_divider_padding_bottom">4dp</dimen>
--- a/mobile/android/app/src/photon/res/values/styles.xml
+++ b/mobile/android/app/src/photon/res/values/styles.xml
@@ -971,9 +971,26 @@
     </style>
 
     <style name="TabStrip.Title" parent="TabStrip.V15.Title"/>
     <style name="TabStrip.V15.Title" parent="TabStrip.Base">
         <item name="android:layout_toRightOf">@id/favicon</item>
         <item name="android:layout_toLeftOf">@id/close</item>
     </style>
 
+    <style name="PwaConfirm">
+        <item name="android:layout_width">match_parent</item>
+    </style>
+
+    <style name="PwaConfirm.Title">
+        <item name="android:layout_toRightOf">@id/pwa_confirm_icon_wrap</item>
+        <item name="android:layout_toLeftOf">@id/pwa_confirm_cancel</item>
+    </style>
+
+    <style name="PwaConfirm.Cancel">
+        <item name="android:layout_alignParentRight">true</item>
+    </style>
+
+    <style name="PwaConfirm.Url">
+        <item name="android:layout_alignLeft">@+id/pwa_confirm_title</item>
+    </style>
+
 </resources>
--- a/mobile/android/base/java/org/mozilla/gecko/Tab.java
+++ b/mobile/android/base/java/org/mozilla/gecko/Tab.java
@@ -33,16 +33,18 @@ import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.os.Bundle;
 import android.support.annotation.NonNull;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.View;
 
+import static org.mozilla.gecko.toolbar.PageActionLayout.PageAction.UUID_PAGE_ACTION_PWA;
+
 public class Tab {
     private static final String LOGTAG = "GeckoTab";
 
     private static Pattern sColorPattern;
     private final int mId;
     private final BrowserDB mDB;
     private long mLastUsed;
     private String mUrl;
@@ -464,20 +466,20 @@ public class Tab {
 
     public void setManifestUrl(String manifestUrl) {
         mManifestUrl = manifestUrl;
         updatePageAction();
     }
 
     public void updatePageAction() {
         if (mManifestUrl != null) {
-            PageActionLayout.PageAction.showPwaPageAction();
+            showPwaPageAction();
 
         } else {
-            PageActionLayout.PageAction.clearPwaPageAction();
+            clearPwaPageAction();
         }
     }
 
     public void setHasOpenSearch(boolean hasOpenSearch) {
         mHasOpenSearch = hasOpenSearch;
     }
 
     public void setLoadedFromCache(boolean loadedFromCache) {
@@ -845,9 +847,26 @@ public class Tab {
 
     public void setShouldShowToolbarWithoutAnimationOnFirstSelection(final boolean shouldShowWithoutAnimation) {
         mShouldShowToolbarWithoutAnimationOnFirstSelection = shouldShowWithoutAnimation;
     }
 
     public boolean getShouldShowToolbarWithoutAnimationOnFirstSelection() {
         return mShouldShowToolbarWithoutAnimationOnFirstSelection;
     }
+
+    private void clearPwaPageAction() {
+        GeckoBundle bundle = new GeckoBundle();
+        bundle.putString("id", UUID_PAGE_ACTION_PWA);
+        EventDispatcher.getInstance().dispatch("PageActions:Remove", bundle);
+    }
+
+    private void showPwaPageAction() {
+        if (!isPrivate()) {
+            GeckoBundle bundle = new GeckoBundle();
+            bundle.putString("id", UUID_PAGE_ACTION_PWA);
+            bundle.putString("title", mAppContext.getString(R.string.pwa_add_to_launcher_badge));
+            bundle.putString("icon", "drawable://add_to_homescreen");
+            bundle.putBoolean("important", true);
+            EventDispatcher.getInstance().dispatch("PageActions:Add", bundle);
+        }
+    }
 }
--- a/mobile/android/base/java/org/mozilla/gecko/toolbar/PageActionLayout.java
+++ b/mobile/android/base/java/org/mozilla/gecko/toolbar/PageActionLayout.java
@@ -1,85 +1,95 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * 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.gecko.toolbar;
 
 import org.mozilla.gecko.EventDispatcher;
-import org.mozilla.gecko.GeckoApplication;
+import org.mozilla.gecko.GeckoSharedPrefs;
 import org.mozilla.gecko.R;
+import org.mozilla.gecko.Tab;
+import org.mozilla.gecko.Tabs;
+import org.mozilla.gecko.preferences.GeckoPreferences;
 import org.mozilla.gecko.util.DrawableUtil;
 import org.mozilla.gecko.util.ResourceDrawableUtils;
 import org.mozilla.gecko.util.BundleEventListener;
 import org.mozilla.gecko.util.EventCallback;
 import org.mozilla.gecko.util.GeckoBundle;
 import org.mozilla.gecko.util.ThreadUtils;
 import org.mozilla.gecko.widget.GeckoPopupMenu;
 import org.mozilla.gecko.widget.themed.ThemedImageButton;
 import org.mozilla.gecko.widget.themed.ThemedLinearLayout;
 
 import android.content.Context;
+import android.content.SharedPreferences;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
 import android.support.v4.content.ContextCompat;
+import android.support.v4.view.ViewCompat;
 import android.util.AttributeSet;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
 import android.widget.ImageButton;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 
 import java.util.Iterator;
 import java.util.List;
 import java.util.UUID;
 import java.util.ArrayList;
 
+import static org.mozilla.gecko.toolbar.PageActionLayout.PageAction.UUID_PAGE_ACTION_PWA;
+
 public class PageActionLayout extends ThemedLinearLayout implements BundleEventListener,
-                                                              View.OnClickListener,
-                                                              View.OnLongClickListener {
+        View.OnClickListener,
+        View.OnLongClickListener {
     private static final String MENU_BUTTON_KEY = "MENU_BUTTON_KEY";
     private static final int DEFAULT_PAGE_ACTIONS_SHOWN = 2;
+    public static final String PREF_PWA_ONBOARDING = GeckoPreferences.NON_PREF_PREFIX + "pref_pwa_onboarding";
+
 
     private final Context mContext;
     private final LinearLayout mLayout;
     private final List<PageAction> mPageActionList;
 
     private GeckoPopupMenu mPageActionsMenu;
 
     // By default it's two, can be changed by calling setNumberShown(int)
     private int mMaxVisiblePageActions;
+    private PwaConfirm mPwaConfirm;
 
     public PageActionLayout(Context context, AttributeSet attrs) {
         super(context, attrs);
         mContext = context;
         mLayout = this;
 
         mPageActionList = new ArrayList<PageAction>();
         setNumberShown(DEFAULT_PAGE_ACTIONS_SHOWN);
         refreshPageActionIcons();
     }
 
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
 
         EventDispatcher.getInstance().registerUiThreadListener(this,
-            "PageActions:Add",
-            "PageActions:Remove");
+                "PageActions:Add",
+                "PageActions:Remove");
     }
 
     @Override
     protected void onDetachedFromWindow() {
         EventDispatcher.getInstance().unregisterUiThreadListener(this,
-            "PageActions:Add",
-            "PageActions:Remove");
+                "PageActions:Add",
+                "PageActions:Remove");
 
         super.onDetachedFromWindow();
     }
 
     @Override
     public void setPrivateMode(boolean isPrivate) {
         super.setPrivateMode(isPrivate);
         for (int i = 0; i < getChildCount(); i++) {
@@ -102,33 +112,38 @@ public class PageActionLayout extends Th
         }
     }
 
     @Override // BundleEventListener
     public void handleMessage(final String event, final GeckoBundle message,
                               final EventCallback callback) {
         ThreadUtils.assertOnUiThread();
 
+        hidePreviousConfirmPrompt();
+
         if ("PageActions:Add".equals(event)) {
             final String id = message.getString("id");
 
             boolean alreadyAdded = isPwaAdded(id);
             if (alreadyAdded) {
                 return;
             }
+
+            maybeShowPwaOnboarding(id);
+
             final String title = message.getString("title");
             final String imageURL = message.getString("icon");
             final boolean important = message.getBoolean("important");
             final boolean useTint = message.getBoolean("useTint");
 
             addPageAction(id, title, imageURL, useTint, new OnPageActionClickListeners() {
                 @Override
                 public void onClick(final String id) {
-                    if (id != null && id.equals(PageAction.UUID_PAGE_ACTION_PWA)) {
-                        GeckoApplication.createShortcut();
+                    if (UUID_PAGE_ACTION_PWA.equals(id)) {
+                        mPwaConfirm = PwaConfirm.show(getContext());
                         return;
                     }
                     final GeckoBundle data = new GeckoBundle(1);
                     data.putString("id", id);
                     EventDispatcher.getInstance().dispatch("PageActions:Clicked", data);
                 }
 
                 @Override
@@ -140,27 +155,43 @@ public class PageActionLayout extends Th
                 }
             }, important);
 
         } else if ("PageActions:Remove".equals(event)) {
             removePageAction(message.getString("id"));
         }
     }
 
+    private void maybeShowPwaOnboarding(String id) {
+        // only show pwa at normal mode
+        final Tab selectedTab = Tabs.getInstance().getSelectedTab();
+        if (selectedTab.isPrivate()) {
+            return;
+        }
+        if (UUID_PAGE_ACTION_PWA.equals(id)) {
+            final SharedPreferences prefs = GeckoSharedPrefs.forApp(getContext());
+            final boolean show = prefs.getBoolean(PREF_PWA_ONBOARDING, true);
+            if (show) {
+                PwaOnboarding.show(getContext());
+                prefs.edit().putBoolean(PREF_PWA_ONBOARDING, false).apply();
+            }
+        }
+    }
+
     private boolean isPwaAdded(String id) {
         for (PageAction pageAction : mPageActionList) {
             if (pageAction.getID() != null && pageAction.getID().equals(id)) {
                 return true;
             }
         }
         return false;
     }
 
     private void addPageAction(final String id, final String title, final String imageData, final boolean useTint,
-            final OnPageActionClickListeners onPageActionClickListeners, boolean important) {
+                               final OnPageActionClickListeners onPageActionClickListeners, boolean important) {
         ThreadUtils.assertOnUiThread();
 
         final PageAction pageAction = new PageAction(id, title, null, onPageActionClickListeners, important);
 
         int insertAt = mPageActionList.size();
         while (insertAt > 0 && mPageActionList.get(insertAt - 1).isImportant()) {
             insertAt--;
         }
@@ -208,29 +239,29 @@ public class PageActionLayout extends Th
         imageButton.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
         imageButton.setOnClickListener(this);
         imageButton.setOnLongClickListener(this);
         return imageButton;
     }
 
     @Override
     public void onClick(View v) {
-        String buttonClickedId = (String)v.getTag();
+        String buttonClickedId = (String) v.getTag();
         if (buttonClickedId != null) {
             if (buttonClickedId.equals(MENU_BUTTON_KEY)) {
                 showMenu(v, mPageActionList.size() - mMaxVisiblePageActions + 1);
             } else {
                 getPageActionWithId(buttonClickedId).onClick();
             }
         }
     }
 
     @Override
     public boolean onLongClick(View v) {
-        String buttonClickedId = (String)v.getTag();
+        String buttonClickedId = (String) v.getTag();
         if (buttonClickedId.equals(MENU_BUTTON_KEY)) {
             showMenu(v, mPageActionList.size() - mMaxVisiblePageActions + 1);
             return true;
         } else {
             return getPageActionWithId(buttonClickedId).onLongClick();
         }
     }
 
@@ -339,19 +370,29 @@ public class PageActionLayout extends Th
             MenuItem item = menu.add(Menu.NONE, pageAction.key(), Menu.NONE, pageAction.getTitle());
             item.setIcon(pageAction.getDrawable());
         }
         mPageActionsMenu.show();
     }
 
     private static interface OnPageActionClickListeners {
         public void onClick(String id);
+
         public boolean onLongClick(String id);
     }
 
+    private void hidePreviousConfirmPrompt() {
+        if (mPwaConfirm != null) {
+            if (ViewCompat.isAttachedToWindow(mPwaConfirm) || mPwaConfirm.getParent() != null) {
+                mPwaConfirm.disappear();
+            }
+            mPwaConfirm = null;
+        }
+    }
+
     public static class PageAction {
         public static final String UUID_PAGE_ACTION_PWA = "279c269d-6397-4f86-a6d2-452e26456d4a";
 
         private final OnPageActionClickListeners mOnPageActionClickListeners;
         private Drawable mDrawable;
         private final String mTitle;
         private final String mId;
         private final int key;
@@ -366,25 +407,16 @@ public class PageActionLayout extends Th
             mTitle = title;
             mDrawable = image;
             mOnPageActionClickListeners = onPageActionClickListeners;
             mImportant = important;
 
             key = UUID.fromString(mId.subSequence(1, mId.length() - 2).toString()).hashCode();
         }
 
-        public static void showPwaPageAction() {
-            GeckoBundle bundle = new GeckoBundle();
-            bundle.putString("id", UUID_PAGE_ACTION_PWA);
-            bundle.putString("title", "Add PWA Shortcut");
-            bundle.putString("icon", "drawable://icon_openinapp");
-            bundle.putBoolean("important", true);
-            EventDispatcher.getInstance().dispatch("PageActions:Add", bundle);
-        }
-
         public Drawable getDrawable() {
             return mDrawable;
         }
 
         public void setDrawable(Drawable d) {
             mDrawable = d;
         }
 
@@ -412,15 +444,11 @@ public class PageActionLayout extends Th
 
         public boolean onLongClick() {
             if (mOnPageActionClickListeners != null) {
                 return mOnPageActionClickListeners.onLongClick(mId);
             }
             return false;
         }
 
-        public static void clearPwaPageAction() {
-            GeckoBundle bundle = new GeckoBundle();
-            bundle.putString("id", UUID_PAGE_ACTION_PWA);
-            EventDispatcher.getInstance().dispatch("PageActions:Remove", bundle);
-        }
+
     }
 }
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/java/org/mozilla/gecko/toolbar/PwaConfirm.java
@@ -0,0 +1,143 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * 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.gecko.toolbar;
+
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.app.Activity;
+import android.content.Context;
+import android.support.annotation.Nullable;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import org.mozilla.gecko.GeckoApplication;
+import org.mozilla.gecko.R;
+import org.mozilla.gecko.Tab;
+import org.mozilla.gecko.Tabs;
+
+public class PwaConfirm extends RelativeLayout {
+
+    boolean isAnimating = false;
+
+
+    public static PwaConfirm show(Context context) {
+        if (context instanceof Activity) {
+            final ViewGroup contetView = (ViewGroup) ((Activity) context).findViewById(R.id.gecko_layout);
+            final View oldPwaConfirm = contetView.findViewById(R.id.pwa_confirm_root);
+            if ((oldPwaConfirm != null)) {
+                // prevent this view to be added twice.
+                return (PwaConfirm) oldPwaConfirm;
+            }
+            View parent = LayoutInflater.from(context).inflate(R.layout.pwa_confirm, contetView);
+            final PwaConfirm pwaConfirm = (PwaConfirm) parent.findViewById(R.id.pwa_confirm_root);
+            pwaConfirm.appear();
+            return pwaConfirm;
+        }
+        return null;
+    }
+
+    private void appear() {
+
+        setAlpha(0);
+
+        final Animator alphaAnimator = ObjectAnimator.ofFloat(this, "alpha", 1);
+        alphaAnimator.setStartDelay(200);
+        alphaAnimator.setDuration(300);
+
+
+        alphaAnimator.start();
+    }
+
+    public void disappear() {
+        if (isAnimating) {
+            return;
+        }
+
+        isAnimating = true;
+
+        setAlpha(1);
+
+        final Animator alphaAnimator = ObjectAnimator.ofFloat(this, "alpha", 0);
+        alphaAnimator.setDuration(300);
+
+        alphaAnimator.start();
+        dismiss();
+    }
+
+    public PwaConfirm(Context context) {
+        super(context);
+    }
+
+    public PwaConfirm(Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public PwaConfirm(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        if (isInEditMode()) {
+            return;
+        }
+        init();
+        setupBackpress();
+    }
+
+    private void init() {
+        final OnClickListener dismiss = new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                disappear();
+            }
+        };
+        final OnClickListener createShortcut = new OnClickListener() {
+
+            @Override
+            public void onClick(View v) {
+                GeckoApplication.createShortcut();
+                disappear();
+            }
+        };
+        findViewById(R.id.pwa_confirm_root).setOnClickListener(dismiss);
+        findViewById(R.id.pwa_confirm_cancel).setOnClickListener(dismiss);
+        findViewById(R.id.pwa_confirm_action).setOnClickListener(createShortcut);
+
+
+        final Tab selectedTab = Tabs.getInstance().getSelectedTab();
+
+        if (selectedTab != null) {
+            ((TextView) findViewById(R.id.pwa_confirm_title)).setText(selectedTab.getTitle());
+            ((TextView) findViewById(R.id.pwa_confirm_url)).setText(selectedTab.getURL());
+            ((ImageView) findViewById(R.id.pwa_confirm_icon)).setImageBitmap(selectedTab.getFavicon());
+        }
+    }
+
+    private void setupBackpress() {
+        setFocusableInTouchMode(true);
+        requestFocus();
+        setOnKeyListener(new OnKeyListener() {
+            @Override
+            public boolean onKey(View v, int keyCode, KeyEvent event) {
+                if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
+                    dismiss();
+                }
+                return true;
+            }
+        });
+    }
+
+    public void dismiss() {
+        ((ViewGroup) PwaConfirm.this.getParent()).removeView(PwaConfirm.this);
+    }
+}
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/java/org/mozilla/gecko/toolbar/PwaOnboarding.java
@@ -0,0 +1,89 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * 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.gecko.toolbar;
+
+import android.app.Activity;
+import android.content.Context;
+import android.support.annotation.Nullable;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+
+import org.mozilla.gecko.R;
+import org.mozilla.gecko.Tabs;
+
+public class PwaOnboarding extends RelativeLayout {
+
+    static final String LINK_PWA_SUMO = "https://developer.mozilla.org/en-US/Apps/Progressive";
+
+    public static void show(Context context) {
+        if (context instanceof Activity) {
+            final ViewGroup contetView = (ViewGroup) ((Activity) context).findViewById(android.R.id.content);
+            LayoutInflater.from(context).inflate(R.layout.pwa_onboarding, contetView);
+        }
+    }
+
+    public PwaOnboarding(Context context) {
+        super(context);
+    }
+
+    public PwaOnboarding(Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public PwaOnboarding(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        init();
+        setupBackpress();
+    }
+
+    private void init() {
+        final OnClickListener dismiss = new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                dismiss();
+            }
+        };
+        final OnClickListener loadSumo = new OnClickListener() {
+
+            @Override
+            public void onClick(View v) {
+                dismiss();
+                Tabs.getInstance().loadUrlInTab(LINK_PWA_SUMO);
+            }
+        };
+        findViewById(R.id.pwa_onboarding_root).setOnClickListener(dismiss);
+        findViewById(R.id.pwa_onboarding_dismiss).setOnClickListener(dismiss);
+        findViewById(R.id.pwa_onboarding_sumo).setOnClickListener(loadSumo);
+    }
+
+
+    private void setupBackpress() {
+        setFocusableInTouchMode(true);
+        requestFocus();
+        setOnKeyListener(new OnKeyListener() {
+            @Override
+            public boolean onKey(View v, int keyCode, KeyEvent event) {
+                if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
+                    dismiss();
+                }
+                return true;
+            }
+        });
+    }
+
+    private void dismiss() {
+        ((ViewGroup) this.getParent()).removeView(this);
+    }
+}
--- a/mobile/android/base/java/org/mozilla/gecko/util/UnusedResourcesUtil.java
+++ b/mobile/android/base/java/org/mozilla/gecko/util/UnusedResourcesUtil.java
@@ -94,9 +94,13 @@ final class UnusedResourcesUtil {
             R.xml.preferences_default_browser_tablet
     };
 
     // String resources that are used in the full-pane Activity Stream that are temporarily
     // not needed while Activity Stream is part of the HomePager
     public static final int[] TEMPORARY_UNUSED_ACTIVITY_STREAM = {
             R.string.activity_stream_topsites
     };
+
+    public static final int[] USED_IN_PAGE_ACTION = {
+            R.drawable.add_to_homescreen
+    };
 }
--- a/mobile/android/base/locales/en-US/android_strings.dtd
+++ b/mobile/android/base/locales/en-US/android_strings.dtd
@@ -848,8 +848,14 @@ is simply hidden from the Activity Strea
 <!ENTITY activity_stream_delete_history "Delete from History">
 
 <!ENTITY private_tab_panel_title "Private Browsing + Tracking Protection">
 <!ENTITY private_tab_panel_description "&brandShortName; blocks parts of the pages that may track your browsing activity.">
 <!ENTITY private_tab_panel_description2 "We won\'t remember any history, but downloaded files and new bookmarks will still be saved to your device.">
 <!ENTITY private_tab_learn_more "Want to learn more?">
 
 <!ENTITY fullscreen_warning "Entered full screen">
+
+
+<!ENTITY pwa_add_to_launcher_confirm "+ Add to Home Screen">
+<!ENTITY pwa_add_to_launcher_badge "Add PWA to Home Screen">
+<!ENTITY pwa_continue_to_website "Continue to Website">
+<!ENTITY pwa_onboarding_sumo "You can easily add this website to your Home screen to have instant access and browse faster with an app-like experience.">
\ No newline at end of file
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -924,16 +924,18 @@ gbjar.sources += ['java/org/mozilla/geck
     'toolbar/BackButton.java',
     'toolbar/BrowserToolbar.java',
     'toolbar/BrowserToolbarPhone.java',
     'toolbar/BrowserToolbarPhoneBase.java',
     'toolbar/CanvasDelegate.java',
     'toolbar/NavButton.java',
     'toolbar/PageActionLayout.java',
     'toolbar/PhoneTabsButton.java',
+    'toolbar/PwaConfirm.java',
+    'toolbar/PwaOnboarding.java',
     'toolbar/SecurityModeUtil.java',
     'toolbar/ShapedButton.java',
     'toolbar/ShapedButtonFrameLayout.java',
     'toolbar/SiteIdentityPopup.java',
     'toolbar/ToolbarEditLayout.java',
     'toolbar/ToolbarEditText.java',
     'toolbar/ToolbarPrefs.java',
     'trackingprotection/TrackingProtectionPrompt.java',
--- a/mobile/android/base/strings.xml.in
+++ b/mobile/android/base/strings.xml.in
@@ -634,9 +634,14 @@
   <string name="activity_stream_highlights_empty">&activity_stream_highlights_empty;</string>
 
   <string name="private_tab_panel_title">&private_tab_panel_title;</string>
   <string name="private_tab_panel_description">&private_tab_panel_description;</string>
   <string name="private_tab_panel_description2">&private_tab_panel_description2;</string>
   <string name="private_tab_learn_more">&private_tab_learn_more;</string>
 
   <string name="fullscreen_warning">&fullscreen_warning;</string>
+
+  <string name="pwa_add_to_launcher_confirm">&pwa_add_to_launcher_confirm;</string>
+  <string name="pwa_add_to_launcher_badge">&pwa_add_to_launcher_badge;</string>
+  <string name="pwa_onboarding_sumo">&pwa_onboarding_sumo;</string>
+  <string name="pwa_continue_to_website">&pwa_continue_to_website;</string>
 </resources>