Commit 56a3dba9 authored by dfalcantara's avatar dfalcantara Committed by Commit bot

Start piping Android app promos through AppBannerInfoBars

* Use AppBannerInfoBars instead of AppBannerViews for Android
  app promos.

- Button doesn't install anything.

- Layout is still incorrect.

BUG=453170

Review URL: https://codereview.chromium.org/896243004

Cr-Commit-Position: refs/heads/master@{#315104}
parent f0fdb821
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
package org.chromium.chrome.browser.banners; package org.chromium.chrome.browser.banners;
import android.app.PendingIntent;
import android.text.TextUtils; import android.text.TextUtils;
import org.chromium.base.ApplicationStatus; import org.chromium.base.ApplicationStatus;
...@@ -13,23 +12,21 @@ import org.chromium.base.JNINamespace; ...@@ -13,23 +12,21 @@ import org.chromium.base.JNINamespace;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.EmptyTabObserver; import org.chromium.chrome.browser.EmptyTabObserver;
import org.chromium.chrome.browser.Tab; import org.chromium.chrome.browser.Tab;
import org.chromium.content.browser.ContentViewCore;
import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContents;
/** /**
* Manages an AppBannerView for a Tab and its ContentView. * Manages an AppBannerInfoBar for a Tab.
* *
* The AppBannerManager manages a single AppBannerView, dismissing it when the user navigates to a * The AppBannerManager manages a single AppBannerInfoBar, creating a new one when it detects that
* new page or creating a new one when it detects that the current webpage is requesting a banner to * the current webpage is requesting a banner to be built. The actual observation of the WebContents
* be built. The actual observation of the WebContents (which triggers the automatic creation and * (which triggers the automatic creation and removal of banners, among other things) is done by the
* removal of banners, among other things) is done by the native-side AppBannerManager. * native-side AppBannerManager.
* *
* This Java-side class owns its native-side counterpart, which is basically used to grab resources * This Java-side class owns its native-side counterpart, which is basically used to grab resources
* from the network. * from the network.
*/ */
@JNINamespace("banners") @JNINamespace("banners")
public class AppBannerManager extends EmptyTabObserver public class AppBannerManager extends EmptyTabObserver implements AppDetailsDelegate.Observer {
implements AppBannerView.Observer, AppDetailsDelegate.Observer {
private static final String TAG = "AppBannerManager"; private static final String TAG = "AppBannerManager";
/** Retrieves information about a given package. */ /** Retrieves information about a given package. */
...@@ -41,15 +38,6 @@ public class AppBannerManager extends EmptyTabObserver ...@@ -41,15 +38,6 @@ public class AppBannerManager extends EmptyTabObserver
/** Tab that the AppBannerView/AppBannerManager is owned by. */ /** Tab that the AppBannerView/AppBannerManager is owned by. */
private final Tab mTab; private final Tab mTab;
/** ContentViewCore that the AppBannerView/AppBannerManager is currently attached to. */
private ContentViewCore mContentViewCore;
/** Current banner being shown. */
private AppBannerView mBannerView;
/** Data about the app being advertised. */
private AppData mAppData;
/** /**
* Checks if app banners are enabled. * Checks if app banners are enabled.
* @return True if banners are enabled, false otherwise. * @return True if banners are enabled, false otherwise.
...@@ -93,15 +81,12 @@ public class AppBannerManager extends EmptyTabObserver ...@@ -93,15 +81,12 @@ public class AppBannerManager extends EmptyTabObserver
*/ */
public void destroy() { public void destroy() {
nativeDestroy(mNativePointer); nativeDestroy(mNativePointer);
resetState();
} }
/** /**
* Updates which ContentView and WebContents the AppBannerView is monitoring. * Updates which WebContents the native AppBannerManager is monitoring.
*/ */
private void updatePointers() { private void updatePointers() {
if (mContentViewCore != mTab.getContentViewCore())
mContentViewCore = mTab.getContentViewCore();
nativeReplaceWebContents(mNativePointer, mTab.getWebContents()); nativeReplaceWebContents(mNativePointer, mTab.getWebContents());
} }
...@@ -117,9 +102,8 @@ public class AppBannerManager extends EmptyTabObserver ...@@ -117,9 +102,8 @@ public class AppBannerManager extends EmptyTabObserver
* @param packageName Name of the package that is being advertised. * @param packageName Name of the package that is being advertised.
*/ */
@CalledByNative @CalledByNative
private void prepareBanner(String url, String packageName) { private void fetchAppDetails(String url, String packageName) {
if (sAppDetailsDelegate == null || !isBannerForCurrentPage(url)) return; if (sAppDetailsDelegate == null) return;
int iconSize = getPreferredIconSize(); int iconSize = getPreferredIconSize();
sAppDetailsDelegate.getAppDetailsAsynchronously(this, url, packageName, iconSize); sAppDetailsDelegate.getAppDetailsAsynchronously(this, url, packageName, iconSize);
} }
...@@ -131,63 +115,13 @@ public class AppBannerManager extends EmptyTabObserver ...@@ -131,63 +115,13 @@ public class AppBannerManager extends EmptyTabObserver
*/ */
@Override @Override
public void onAppDetailsRetrieved(AppData data) { public void onAppDetailsRetrieved(AppData data) {
if (data == null || !isBannerForCurrentPage(data.siteUrl())) return; if (data == null) return;
mAppData = data;
String imageUrl = data.imageUrl(); String imageUrl = data.imageUrl();
if (TextUtils.isEmpty(imageUrl) || !nativeFetchIcon(mNativePointer, imageUrl)) resetState(); if (TextUtils.isEmpty(imageUrl)) return;
}
@Override
public void onBannerRemoved(AppBannerView banner) {
if (mBannerView != banner) return;
resetState();
}
@Override
public void onBannerBlocked(AppBannerView banner, String url, String packageName) {
if (mBannerView != banner) return;
nativeBlockBanner(mNativePointer, url, packageName);
}
@Override
public void onBannerDismissEvent(AppBannerView banner, int eventType) {
if (mBannerView != banner) return;
nativeRecordDismissEvent(eventType);
}
@Override nativeOnAppDetailsRetrieved(
public void onBannerInstallEvent(AppBannerView banner, int eventType) { mNativePointer, data, data.title(), data.packageName(), data.imageUrl());
if (mBannerView != banner) return;
nativeRecordInstallEvent(eventType);
}
@Override
public boolean onFireIntent(AppBannerView banner, PendingIntent intent) {
if (mBannerView != banner) return false;
return mTab.getWindowAndroid().showIntent(intent, banner, R.string.low_memory_error);
}
/**
* Resets all of the state, killing off any running tasks.
*/
private void resetState() {
if (mBannerView != null) {
mBannerView.destroy();
mBannerView = null;
}
mAppData = null;
}
/**
* Checks to see if the banner is for the currently displayed page.
* @param bannerUrl URL that requested a banner.
* @return True if the user is still on the same page.
*/
private boolean isBannerForCurrentPage(String bannerUrl) {
return mContentViewCore != null
&& TextUtils.equals(mContentViewCore.getWebContents().getUrl(), bannerUrl);
} }
private static native boolean nativeIsEnabled(); private static native boolean nativeIsEnabled();
...@@ -195,9 +129,8 @@ public class AppBannerManager extends EmptyTabObserver ...@@ -195,9 +129,8 @@ public class AppBannerManager extends EmptyTabObserver
private native void nativeDestroy(long nativeAppBannerManager); private native void nativeDestroy(long nativeAppBannerManager);
private native void nativeReplaceWebContents(long nativeAppBannerManager, private native void nativeReplaceWebContents(long nativeAppBannerManager,
WebContents webContents); WebContents webContents);
private native void nativeBlockBanner( private native boolean nativeOnAppDetailsRetrieved(long nativeAppBannerManager, AppData data,
long nativeAppBannerManager, String url, String packageName); String title, String packageName, String imageUrl);
private native boolean nativeFetchIcon(long nativeAppBannerManager, String imageUrl);
// UMA tracking. // UMA tracking.
private static native void nativeRecordDismissEvent(int metric); private static native void nativeRecordDismissEvent(int metric);
......
...@@ -61,6 +61,8 @@ import org.chromium.ui.base.WindowAndroid.IntentCallback; ...@@ -61,6 +61,8 @@ import org.chromium.ui.base.WindowAndroid.IntentCallback;
* The layout of the banner, which includes its widget sizes, may change when the screen is rotated * The layout of the banner, which includes its widget sizes, may change when the screen is rotated
* to account for less screen real estate. This means that all of the View's widgets and cached * to account for less screen real estate. This means that all of the View's widgets and cached
* dimensions must be rebuilt from scratch. * dimensions must be rebuilt from scratch.
*
* TODO(dfalcantara): Nuke this file.
*/ */
public class AppBannerView extends SwipableOverlayView public class AppBannerView extends SwipableOverlayView
implements View.OnClickListener, InstallerDelegate.Observer, IntentCallback { implements View.OnClickListener, InstallerDelegate.Observer, IntentCallback {
...@@ -244,9 +246,7 @@ public class AppBannerView extends SwipableOverlayView ...@@ -244,9 +246,7 @@ public class AppBannerView extends SwipableOverlayView
// Configure the controls with the package information. // Configure the controls with the package information.
mTitleView.setText(mAppData.title()); mTitleView.setText(mAppData.title());
mIconView.setImageDrawable(mAppData.icon());
mRatingView.initialize(mAppData.rating()); mRatingView.initialize(mAppData.rating());
setAccessibilityInformation();
// Determine how much the user can drag sideways before their touch is considered a scroll. // Determine how much the user can drag sideways before their touch is considered a scroll.
mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
...@@ -255,15 +255,6 @@ public class AppBannerView extends SwipableOverlayView ...@@ -255,15 +255,6 @@ public class AppBannerView extends SwipableOverlayView
updateButtonStatus(); updateButtonStatus();
} }
/**
* Creates a succinct description about the app being advertised.
*/
private void setAccessibilityInformation() {
String bannerText = getContext().getString(
R.string.app_banner_view_accessibility, mAppData.title(), mAppData.rating());
setContentDescription(bannerText);
}
@Override @Override
public void onClick(View view) { public void onClick(View view) {
if (mObserver == null) return; if (mObserver == null) return;
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
package org.chromium.chrome.browser.banners; package org.chromium.chrome.browser.banners;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.graphics.drawable.Drawable;
/** /**
* Stores information about a particular app. * Stores information about a particular app.
...@@ -23,9 +22,6 @@ public class AppData { ...@@ -23,9 +22,6 @@ public class AppData {
private PendingIntent mDetailsIntent; private PendingIntent mDetailsIntent;
private PendingIntent mInstallIntent; private PendingIntent mInstallIntent;
// Data that can be updated asynchronously.
private Drawable mIcon;
/** /**
* Creates a new AppData for the given page and package. * Creates a new AppData for the given page and package.
* @param siteUrl URL for the site requesting the banner. * @param siteUrl URL for the site requesting the banner.
...@@ -56,7 +52,7 @@ public class AppData { ...@@ -56,7 +52,7 @@ public class AppData {
* Returns the title to display for the app in the banner. * Returns the title to display for the app in the banner.
* @return The String to display. * @return The String to display.
*/ */
String title() { public String title() {
return mTitle; return mTitle;
} }
...@@ -68,19 +64,11 @@ public class AppData { ...@@ -68,19 +64,11 @@ public class AppData {
return mImageUrl; return mImageUrl;
} }
/**
* Returns the Drawable depicting the app's icon.
* @return The Drawable to use as the app icon.
*/
Drawable icon() {
return mIcon;
}
/** /**
* Returns how well the app was rated, on a scale from 0 to 5. * Returns how well the app was rated, on a scale from 0 to 5.
* @return The rating of the app. * @return The rating of the app.
*/ */
float rating() { public float rating() {
return mRating; return mRating;
} }
...@@ -88,7 +76,7 @@ public class AppData { ...@@ -88,7 +76,7 @@ public class AppData {
* Returns text to display on the install button when the app is not installed on the system. * Returns text to display on the install button when the app is not installed on the system.
* @return The String to display. * @return The String to display.
*/ */
String installButtonText() { public String installButtonText() {
return mInstallButtonText; return mInstallButtonText;
} }
...@@ -97,7 +85,7 @@ public class AppData { ...@@ -97,7 +85,7 @@ public class AppData {
* The IntentSender stored inside dictates what package needs to be launched. * The IntentSender stored inside dictates what package needs to be launched.
* @return Intent that triggers the details page. * @return Intent that triggers the details page.
*/ */
PendingIntent detailsIntent() { public PendingIntent detailsIntent() {
return mDetailsIntent; return mDetailsIntent;
} }
...@@ -128,12 +116,4 @@ public class AppData { ...@@ -128,12 +116,4 @@ public class AppData {
mDetailsIntent = detailsIntent; mDetailsIntent = detailsIntent;
mInstallIntent = installIntent; mInstallIntent = installIntent;
} }
/**
* Sets the icon used to depict the app.
* @param Drawable App icon in Drawable form.
*/
void setIcon(Drawable icon) {
mIcon = icon;
}
} }
...@@ -4,41 +4,79 @@ ...@@ -4,41 +4,79 @@
package org.chromium.chrome.browser.infobar; package org.chromium.chrome.browser.infobar;
import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.widget.TextView; import android.widget.TextView;
import org.chromium.base.ApplicationStatus; import org.chromium.base.ApplicationStatus;
import org.chromium.base.CalledByNative; import org.chromium.base.CalledByNative;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.banners.AppData;
/** /**
* Infobar informing the user about an app related to this page. * Infobar informing the user about an app related to this page.
*/ */
public class AppBannerInfoBar extends ConfirmInfoBar { public class AppBannerInfoBar extends ConfirmInfoBar {
/** Web app: URL pointing to the web app. */ private final String mAppTitle;
// Data for native app installs.
private final AppData mAppData;
// Data for web app installs.
private final String mAppUrl; private final String mAppUrl;
// Banner for native apps.
private AppBannerInfoBar(long nativeInfoBar, String appTitle, Bitmap iconBitmap, AppData data) {
super(nativeInfoBar, null, 0, iconBitmap, appTitle, null, data.installButtonText(), null);
mAppTitle = appTitle;
mAppData = data;
mAppUrl = null;
}
// Banner for web apps. // Banner for web apps.
public AppBannerInfoBar(long nativeInfoBar, String appTitle, Bitmap iconBitmap, String url) { private AppBannerInfoBar(long nativeInfoBar, String appTitle, Bitmap iconBitmap, String url) {
super(nativeInfoBar, null, 0, iconBitmap, appTitle, null, getAddToHomescreenText(), null); super(nativeInfoBar, null, 0, iconBitmap, appTitle, null, getAddToHomescreenText(), null);
mAppTitle = appTitle;
mAppData = null;
mAppUrl = url; mAppUrl = url;
} }
@Override @Override
public void createContent(InfoBarLayout layout) { public void createContent(InfoBarLayout layout) {
TextView url = new TextView(layout.getContext()); if (mAppUrl != null) {
url.setText(mAppUrl); TextView url = new TextView(layout.getContext());
layout.setCustomContent(url); url.setText(mAppUrl);
layout.setCustomContent(url);
}
super.createContent(layout); super.createContent(layout);
// Set up accessibility text.
Context context = getContext();
if (mAppData != null) {
layout.setContentDescription(context.getString(
R.string.app_banner_view_native_app_accessibility, mAppTitle,
mAppData.rating()));
} else {
layout.setContentDescription(context.getString(
R.string.app_banner_view_web_app_accessibility, mAppTitle,
mAppUrl));
}
} }
private static String getAddToHomescreenText() { private static String getAddToHomescreenText() {
return ApplicationStatus.getApplicationContext().getString(R.string.menu_add_to_homescreen); return ApplicationStatus.getApplicationContext().getString(R.string.menu_add_to_homescreen);
} }
@CalledByNative
private static InfoBar createNativeAppInfoBar(
long nativeInfoBar, String appTitle, Bitmap iconBitmap, AppData appData) {
return new AppBannerInfoBar(nativeInfoBar, appTitle, iconBitmap, appData);
}
@CalledByNative @CalledByNative
private static InfoBar createWebAppInfoBar( private static InfoBar createWebAppInfoBar(
long nativeInfoBar, String appTitle, Bitmap iconBitmap, String url) { long nativeInfoBar, String appTitle, Bitmap iconBitmap, String url) {
return new AppBannerInfoBar(nativeInfoBar, appTitle, iconBitmap, url); return new AppBannerInfoBar(nativeInfoBar, appTitle, iconBitmap, url);
} }
} }
\ No newline at end of file
...@@ -829,7 +829,10 @@ You are signing in with a managed account and giving its administrator control o ...@@ -829,7 +829,10 @@ You are signing in with a managed account and giving its administrator control o
</message> </message>
<!-- App banner accessibility strings, used for touch exploration --> <!-- App banner accessibility strings, used for touch exploration -->
<message name="IDS_APP_BANNER_VIEW_ACCESSIBILITY" desc="Accessibililty text: Describes the banner content, including the app name and rating."> <message name="IDS_APP_BANNER_VIEW_WEB_APP_ACCESSIBILITY" desc="Accessibililty text: Describes the banner content, including the app name and its URL.">
Prompt to add page to the homescreen. App name: <ph name="APP_NAME">%1$s<ex>Gmail</ex></ph>. App URL: <ph name="APP_URL">%2$s<ex>http://gmail.com</ex></ph>.
</message>
<message name="IDS_APP_BANNER_VIEW_NATIVE_APP_ACCESSIBILITY" desc="Accessibililty text: Describes the banner content, including the app name and rating.">
Prompt to get app from the Google Play Store. App name: <ph name="APP_NAME">%1$s<ex>Gmail</ex></ph>. App average rating: <ph name="APP_RATING">%2$.1f<ex>4.2</ex></ph>. Prompt to get app from the Google Play Store. App name: <ph name="APP_NAME">%1$s<ex>Gmail</ex></ph>. App average rating: <ph name="APP_RATING">%2$.1f<ex>4.2</ex></ph>.
</message> </message>
<message name="IDS_APP_BANNER_INSTALL_ACCESSIBILITY" desc="Accessibility text: Indicates that clicking on the button will purchase the app or install it."> <message name="IDS_APP_BANNER_INSTALL_ACCESSIBILITY" desc="Accessibility text: Indicates that clicking on the button will purchase the app or install it.">
......
...@@ -14,6 +14,18 @@ ...@@ -14,6 +14,18 @@
namespace banners { namespace banners {
// static
AppBannerInfoBar* AppBannerInfoBarDelegate::CreateForNativeApp(
infobars::InfoBarManager* infobar_manager,
AppDelegate* app_delegate,
const base::android::ScopedJavaGlobalRef<jobject>& japp_data) {
scoped_ptr<AppBannerInfoBarDelegate> delegate(new AppBannerInfoBarDelegate(
app_delegate));
AppBannerInfoBar* infobar = new AppBannerInfoBar(delegate.Pass(), japp_data);
return infobar_manager->AddInfoBar(make_scoped_ptr(infobar))
? infobar : nullptr;
}
// static // static
AppBannerInfoBar* AppBannerInfoBarDelegate::CreateForWebApp( AppBannerInfoBar* AppBannerInfoBarDelegate::CreateForWebApp(
infobars::InfoBarManager* infobar_manager, infobars::InfoBarManager* infobar_manager,
......
...@@ -43,6 +43,13 @@ class AppBannerInfoBarDelegate : public ConfirmInfoBarDelegate { ...@@ -43,6 +43,13 @@ class AppBannerInfoBarDelegate : public ConfirmInfoBarDelegate {
virtual gfx::Image GetIcon() const = 0; virtual gfx::Image GetIcon() const = 0;
}; };
// Creates a banner for the current page that promotes a native app.
// May return nullptr if the the infobar couldn't be created.
static AppBannerInfoBar* CreateForNativeApp(
infobars::InfoBarManager* infobar_manager,
AppDelegate* delegate,
const base::android::ScopedJavaGlobalRef<jobject>& japp_data);
// Creates a banner for the current page that promotes a web app. // Creates a banner for the current page that promotes a web app.
// May return nullptr if the the infobar couldn't be created. // May return nullptr if the the infobar couldn't be created.
static AppBannerInfoBar* CreateForWebApp( static AppBannerInfoBar* CreateForWebApp(
......
...@@ -78,7 +78,12 @@ void AppBannerManager::Block() const { ...@@ -78,7 +78,12 @@ void AppBannerManager::Block() const {
if (!web_contents()) if (!web_contents())
return; return;
if (!web_app_data_.IsEmpty()) { if (!native_app_data_.is_null()) {
AppBannerSettingsHelper::RecordBannerEvent(
web_contents(), web_contents()->GetURL(),
native_app_package_,
AppBannerSettingsHelper::APP_BANNER_EVENT_DID_BLOCK, base::Time::Now());
} else if (!web_app_data_.IsEmpty()) {
AppBannerSettingsHelper::RecordBannerEvent( AppBannerSettingsHelper::RecordBannerEvent(
web_contents(), web_contents()->GetURL(), web_contents(), web_contents()->GetURL(),
web_app_data_.start_url.spec(), web_app_data_.start_url.spec(),
...@@ -132,6 +137,8 @@ void AppBannerManager::DidNavigateMainFrame( ...@@ -132,6 +137,8 @@ void AppBannerManager::DidNavigateMainFrame(
app_title_ = base::string16(); app_title_ = base::string16();
app_icon_.reset(); app_icon_.reset();
web_app_data_ = content::Manifest(); web_app_data_ = content::Manifest();
native_app_data_.Reset();
native_app_package_ = std::string();
} }
void AppBannerManager::DidFinishLoad( void AppBannerManager::DidFinishLoad(
...@@ -247,7 +254,12 @@ void AppBannerManager::OnFetchComplete(const GURL url, const SkBitmap* bitmap) { ...@@ -247,7 +254,12 @@ void AppBannerManager::OnFetchComplete(const GURL url, const SkBitmap* bitmap) {
InfoBarService* service = InfoBarService::FromWebContents(web_contents()); InfoBarService* service = InfoBarService::FromWebContents(web_contents());
weak_infobar_ptr_ = nullptr; weak_infobar_ptr_ = nullptr;
if (!web_app_data_.IsEmpty()){ if (!native_app_data_.is_null()) {
weak_infobar_ptr_ = AppBannerInfoBarDelegate::CreateForNativeApp(
service,
this,
native_app_data_);
} else if (!web_app_data_.IsEmpty()){
weak_infobar_ptr_ = AppBannerInfoBarDelegate::CreateForWebApp( weak_infobar_ptr_ = AppBannerInfoBarDelegate::CreateForWebApp(
service, service,
this, this,
...@@ -285,16 +297,25 @@ void AppBannerManager::OnDidRetrieveMetaTagContent( ...@@ -285,16 +297,25 @@ void AppBannerManager::OnDidRetrieveMetaTagContent(
ConvertUTF8ToJavaString(env, expected_url.spec())); ConvertUTF8ToJavaString(env, expected_url.spec()));
ScopedJavaLocalRef<jstring> jpackage( ScopedJavaLocalRef<jstring> jpackage(
ConvertUTF8ToJavaString(env, tag_content)); ConvertUTF8ToJavaString(env, tag_content));
Java_AppBannerManager_prepareBanner(env, Java_AppBannerManager_fetchAppDetails(env,
jobj.obj(), jobj.obj(),
jurl.obj(), jurl.obj(),
jpackage.obj()); jpackage.obj());
} }
bool AppBannerManager::FetchIcon(JNIEnv* env, bool AppBannerManager::OnAppDetailsRetrieved(JNIEnv* env,
jobject obj, jobject obj,
jstring jimage_url) { jobject japp_data,
std::string image_url = ConvertJavaStringToUTF8(env, jimage_url); jstring japp_title,
jstring japp_package,
jstring jicon_url) {
if (validated_url_ != web_contents()->GetURL())
return false;
std::string image_url = ConvertJavaStringToUTF8(env, jicon_url);
app_title_ = ConvertJavaStringToUTF16(env, japp_title);
native_app_package_ = ConvertJavaStringToUTF8(env, japp_package);
native_app_data_.Reset(env, japp_data);
return FetchIcon(GURL(image_url)); return FetchIcon(GURL(image_url));
} }
......
...@@ -85,11 +85,14 @@ class AppBannerManager : public chrome::BitmapFetcherDelegate, ...@@ -85,11 +85,14 @@ class AppBannerManager : public chrome::BitmapFetcherDelegate,
jobject obj, jobject obj,
jobject jweb_contents); jobject jweb_contents);
// Fetches the icon at the given URL asynchronously. // Called when the Java-side has retrieved information for the app.
// Returns |false| if this couldn't be kicked off. // Returns |false| if an icon fetch couldn't be kicked off.
bool FetchIcon(JNIEnv* env, bool OnAppDetailsRetrieved(JNIEnv* env,
jobject obj, jobject obj,
jstring jimage_url); jobject japp_data,
jstring japp_title,
jstring japp_package,
jstring jicon_url);
// Fetches the icon at the given URL asynchronously. // Fetches the icon at the given URL asynchronously.
// Returns |false| if this couldn't be kicked off. // Returns |false| if this couldn't be kicked off.
...@@ -155,6 +158,9 @@ class AppBannerManager : public chrome::BitmapFetcherDelegate, ...@@ -155,6 +158,9 @@ class AppBannerManager : public chrome::BitmapFetcherDelegate,
content::Manifest web_app_data_; content::Manifest web_app_data_;
base::android::ScopedJavaGlobalRef<jobject> native_app_data_;
std::string native_app_package_;
// Weak pointer to the InfoBar that is being managed. // Weak pointer to the InfoBar that is being managed.
AppBannerInfoBar* weak_infobar_ptr_; AppBannerInfoBar* weak_infobar_ptr_;
......
...@@ -13,6 +13,14 @@ ...@@ -13,6 +13,14 @@
#include "ui/gfx/android/java_bitmap.h" #include "ui/gfx/android/java_bitmap.h"
#include "ui/gfx/image/image.h" #include "ui/gfx/image/image.h"
AppBannerInfoBar::AppBannerInfoBar(
scoped_ptr<banners::AppBannerInfoBarDelegate> delegate,
const base::android::ScopedJavaGlobalRef<jobject>& japp_data)
: ConfirmInfoBar(delegate.Pass()),
japp_data_(japp_data) {
}
AppBannerInfoBar::AppBannerInfoBar( AppBannerInfoBar::AppBannerInfoBar(
scoped_ptr<banners::AppBannerInfoBarDelegate> delegate, scoped_ptr<banners::AppBannerInfoBarDelegate> delegate,
const GURL& app_url) const GURL& app_url)
...@@ -38,22 +46,30 @@ AppBannerInfoBar::CreateRenderInfoBar(JNIEnv* env) { ...@@ -38,22 +46,30 @@ AppBannerInfoBar::CreateRenderInfoBar(JNIEnv* env) {
} }
base::android::ScopedJavaLocalRef<jobject> infobar; base::android::ScopedJavaLocalRef<jobject> infobar;
if (!japp_data_.is_null()) {
infobar.Reset(Java_AppBannerInfoBar_createNativeAppInfoBar(
env,
reinterpret_cast<intptr_t>(this),
app_title.obj(),
java_bitmap.obj(),
japp_data_.obj()));
} else {
// Trim down the app URL to the domain and registry.
std::string trimmed_url =
net::registry_controlled_domains::GetDomainAndRegistry(
app_url_,
net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
// Trim down the app URL to the domain and registry. base::android::ScopedJavaLocalRef<jstring> app_url =
std::string trimmed_url = base::android::ConvertUTF8ToJavaString(env, trimmed_url);
net::registry_controlled_domains::GetDomainAndRegistry(
app_url_,
net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
base::android::ScopedJavaLocalRef<jstring> app_url = infobar.Reset(Java_AppBannerInfoBar_createWebAppInfoBar(
base::android::ConvertUTF8ToJavaString(env, trimmed_url); env,
reinterpret_cast<intptr_t>(this),
infobar.Reset(Java_AppBannerInfoBar_createWebAppInfoBar( app_title.obj(),
env, java_bitmap.obj(),
reinterpret_cast<intptr_t>(this), app_url.obj()));
app_title.obj(), }
java_bitmap.obj(),
app_url.obj()));
java_infobar_.Reset(env, infobar.obj()); java_infobar_.Reset(env, infobar.obj());
return infobar; return infobar;
......
...@@ -17,6 +17,11 @@ class AppBannerInfoBarDelegate; ...@@ -17,6 +17,11 @@ class AppBannerInfoBarDelegate;
class AppBannerInfoBar : public ConfirmInfoBar { class AppBannerInfoBar : public ConfirmInfoBar {
public: public:
// Constructs an AppBannerInfoBar promoting a native app.
AppBannerInfoBar(
scoped_ptr<banners::AppBannerInfoBarDelegate> delegate,
const base::android::ScopedJavaGlobalRef<jobject>& japp_data);
// Constructs an AppBannerInfoBar promoting a web app. // Constructs an AppBannerInfoBar promoting a web app.
AppBannerInfoBar( AppBannerInfoBar(
scoped_ptr<banners::AppBannerInfoBarDelegate> delegate, scoped_ptr<banners::AppBannerInfoBarDelegate> delegate,
...@@ -29,6 +34,9 @@ class AppBannerInfoBar : public ConfirmInfoBar { ...@@ -29,6 +34,9 @@ class AppBannerInfoBar : public ConfirmInfoBar {
base::android::ScopedJavaLocalRef<jobject> CreateRenderInfoBar( base::android::ScopedJavaLocalRef<jobject> CreateRenderInfoBar(
JNIEnv* env) override; JNIEnv* env) override;
// Native app: Details about the app.
base::android::ScopedJavaGlobalRef<jobject> japp_data_;
// Web app: URL for the app. // Web app: URL for the app.
GURL app_url_; GURL app_url_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment