blob: 12ae72a3c791e5add2dff3635a96281599a3ce1e [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_ANDROID_BANNERS_APP_BANNER_MANAGER_H_
#define CHROME_BROWSER_ANDROID_BANNERS_APP_BANNER_MANAGER_H_
#include "base/android/jni_android.h"
#include "base/android/jni_weak_ref.h"
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/android/banners/app_banner_infobar_delegate.h"
#include "chrome/browser/bitmap_fetcher/bitmap_fetcher.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/manifest.h"
namespace content {
struct FrameNavigateParams;
struct LoadCommittedDetails;
struct Manifest;
} // namespace content
/**
* Manages when an app banner is created or dismissed.
*
* Hooks the wiring together for getting the data for a particular app.
* Monitors at most one package at a time, and tracks the info for the
* most recent app that was requested. Any work in progress for other apps is
* discarded.
*
* The procedure for creating a banner spans multiple asynchronous calls across
* the JNI boundary, as well as querying a Service to get info about the app.
*
* 0) A navigation of the main frame is triggered. Upon completion of the load,
* the page is parsed for the correct meta tag. If it doesn't exist, abort.
*
* 1) The AppBannerManager is alerted about the tag's contents, which should
* be the Play Store package name. This is sent to the Java side
* AppBannerManager.
*
* 2) The AppBannerManager's ServiceDelegate is asynchronously queried about the
* package name.
*
* 3) At some point, the Java-side AppBannerManager is alerted of the completed
* query and is given back data about the requested package, which includes a
* URL for the app's icon. This URL is sent to native code for retrieval.
*
* 4) The process of fetching the icon begins by invoking the BitmapFetcher,
* which works asynchonously.
*
* 5) Once the icon has been downloaded, the icon is sent to the Java-side
* AppBannerManager to (finally) create a AppBannerView, assuming that the
* app we retrieved the details for is still for the page that requested it.
*
* Because of the asynchronous nature of this pipeline, it's entirely possible
* that a request to show a banner is interrupted by another request. The
* Java side manages what happens in these situations, which will usually result
* in dropping the old banner request on the floor.
*/
namespace banners {
class AppBannerManager : public chrome::BitmapFetcherDelegate,
public content::WebContentsObserver,
public AppBannerInfoBarDelegate::AppDelegate {
public:
AppBannerManager(JNIEnv* env, jobject obj);
~AppBannerManager() override;
// Destroys the AppBannerManager.
void Destroy(JNIEnv* env, jobject obj);
// Blocks a banner for |package_name| from appearing on the domain for |url|.
void BlockBanner(JNIEnv* env, jobject obj, jstring jurl, jstring jpackage);
// Observes a new WebContents, if necessary.
void ReplaceWebContents(JNIEnv* env,
jobject obj,
jobject jweb_contents);
// Fetches the icon at the given URL asynchronously.
// Returns |false| if this couldn't be kicked off.
bool FetchIcon(JNIEnv* env,
jobject obj,
jstring jimage_url);
// Fetches the icon at the given URL asynchronously.
// Returns |false| if this couldn't be kicked off.
bool FetchIcon(const GURL& image_url);
// Installs the app defined by the manifest.
// TODO(dfalcantara): Fold into Install() when more CLs land.
static void InstallManifestApp(const content::Manifest& manifest,
const SkBitmap& icon);
// WebContentsObserver overrides.
void DidNavigateMainFrame(
const content::LoadCommittedDetails& details,
const content::FrameNavigateParams& params) override;
void DidFinishLoad(content::RenderFrameHost* render_frame_host,
const GURL& validated_url) override;
bool OnMessageReceived(const IPC::Message& message) override;
// BitmapFetcherDelegate overrides.
void OnFetchComplete(const GURL url, const SkBitmap* bitmap) override;
// AppBannerInfoBarDelegate::AppDelegate overrides.
void Block() const override;
void Install() const override;
gfx::Image GetIcon() const override;
private:
// Gets the preferred icon size for the banner icons.
int GetPreferredIconSize();
// Called when the manifest has been retrieved, or if there is no manifest to
// retrieve.
void OnDidGetManifest(const content::Manifest& manifest);
// Called when the renderer has returned information about the meta tag.
// If there is some metadata for the play store tag, this kicks off the
// process of showing a banner for the package designated by |tag_content| on
// the page at the |expected_url|.
void OnDidRetrieveMetaTagContent(bool success,
const std::string& tag_name,
const std::string& tag_content,
const GURL& expected_url);
// Fetches the icon for an app.
scoped_ptr<chrome::BitmapFetcher> fetcher_;
GURL validated_url_;
content::Manifest manifest_;
scoped_ptr<SkBitmap> app_icon_;
// AppBannerManager on the Java side.
JavaObjectWeakGlobalRef weak_java_banner_view_manager_;
DISALLOW_COPY_AND_ASSIGN(AppBannerManager);
}; // class AppBannerManager
// Register native methods
bool RegisterAppBannerManager(JNIEnv* env);
} // namespace banners
#endif // CHROME_BROWSER_ANDROID_BANNERS_APP_BANNER_MANAGER_H_