Bug 1393672 - Show PWA onboarding and confrim prompt r?jwu draft
authorNevin Chen(:nechen) <cnevinchen@gmail.com>
Tue, 26 Sep 2017 15:52:36 +0800
changeset 680413 f474cb4e9f8be2515ae83bdfbdfa172f1ea3c096
parent 679175 cb40c7c037114a7a2a10d09b0e57e7adbfd5ac29
child 681336 da6fba6d8301c04a554f81481d7ad87014453f60
child 682722 13130828202a90307f65ffa1fe9a7ff588572047
child 682768 06fa85e516e58d7b2d4a0c2c1bdd3150387b5fc7
child 682792 6e6db39c3754c0a8fe2334d306cb2e26ae5ecf18
child 682832 e922e935ac5134faa70b0fef7fba088a1d253abe
child 683672 2edd40334aab9901539df291870bc7705a40a2cd
push id84504
push userbmo:cnevinchen@gmail.com
push dateSat, 14 Oct 2017 03:20:28 +0000
reviewersjwu
bugs1393672
milestone58.0a1
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
@@ -36,9 +36,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
@@ -202,17 +202,23 @@
 
     <style name="UrlBar.SiteIdentity" parent="UrlBar.V15.SiteIdentity" />
 
     <style name="UrlBar.V15.SiteIdentity" parent="UrlBar.Base.SiteIdentity">
         <item name="android:layout_marginLeft">8dp</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
@@ -106,9 +106,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
@@ -967,9 +967,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>