| // Copyright 2015 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_BANNERS_APP_BANNER_MANAGER_H_ |
| #define CHROME_BROWSER_BANNERS_APP_BANNER_MANAGER_H_ |
| |
| #include <memory> |
| #include <vector> |
| |
| #include "base/callback_forward.h" |
| #include "base/macros.h" |
| #include "base/memory/weak_ptr.h" |
| #include "chrome/browser/engagement/site_engagement_observer.h" |
| #include "chrome/browser/installable/installable_logging.h" |
| #include "chrome/browser/installable/installable_manager.h" |
| #include "content/public/browser/web_contents_observer.h" |
| #include "mojo/public/cpp/bindings/binding.h" |
| #include "third_party/WebKit/public/platform/modules/app_banner/app_banner.mojom.h" |
| |
| class SkBitmap; |
| struct WebApplicationInfo; |
| |
| namespace content { |
| class RenderFrameHost; |
| class WebContents; |
| } |
| |
| // This forward declaration exists solely for the DidFinishCreatingBookmarkApp |
| // callback, implemented and called on desktop platforms only. |
| namespace extensions { |
| class Extension; |
| } |
| |
| namespace banners { |
| |
| // Coordinates the creation of an app banner, from detecting eligibility to |
| // fetching data and creating the infobar. Sites declare that they want an app |
| // banner using the web app manifest. One web/native app may occupy the pipeline |
| // at a time; navigation resets the manager and discards any work in progress. |
| // |
| // This class contains the generic functionality shared between all platforms, |
| // as well as no-op callbacks that the platform-specific implementations pass to |
| // base::Bind. This allows a WeakPtrFactory to be housed in this class. |
| // |
| // The InstallableManager fetches and validates whether a site is eligible for |
| // banners. The manager is first called to fetch the manifest, so we can verify |
| // whether the site is already installed (and on Android, divert the flow to a |
| // native app banner if requested). The second call completes the checking for a |
| // web app banner (checking manifest validity, service worker, and icon). |
| class AppBannerManager : public content::WebContentsObserver, |
| public blink::mojom::AppBannerService, |
| public SiteEngagementObserver { |
| public: |
| // Returns the current time. |
| static base::Time GetCurrentTime(); |
| |
| // Fast-forwards the current time for testing. |
| static void SetTimeDeltaForTesting(int days); |
| |
| // Sets the weights applied to direct and indirect navigations for triggering |
| // the banner. Deprecated and will be removed when app banners fully migrates |
| // to using site engagement as a trigger. |
| static void SetEngagementWeights(double direct_engagement, |
| double indirect_engagement); |
| |
| // Returns whether or not the URLs match for everything except for the ref. |
| static bool URLsAreForTheSamePage(const GURL& first, const GURL& second); |
| |
| // Requests an app banner. If |is_debug_mode| is true, any failure in the |
| // pipeline will be reported to the devtools console. |
| virtual void RequestAppBanner(const GURL& validated_url, bool is_debug_mode); |
| |
| // Sends a message to the renderer that the user accepted the banner. Does |
| // nothing if |request_id| does not match the current request. |
| void SendBannerAccepted(int request_id); |
| |
| // Sends a message to the renderer that the user dismissed the banner. Does |
| // nothing if |request_id| does not match the current request. |
| void SendBannerDismissed(int request_id); |
| |
| // Overridden and passed through base::Bind on desktop platforms. Called when |
| // the bookmark app install initiated by a banner has completed. Not used on |
| // Android. |
| virtual void DidFinishCreatingBookmarkApp( |
| const extensions::Extension* extension, |
| const WebApplicationInfo& web_app_info) {} |
| |
| // Overridden and passed through base::Bind on Android. Called when the |
| // download of a native app's icon is complete, as native banners use an icon |
| // provided from the Play Store rather than the web manifest. Not used on |
| // desktop platforms. |
| virtual void OnAppIconFetched(const SkBitmap& bitmap) {} |
| |
| // Overridden and passed through base::Bind on Android. Called after a web app |
| // banner was successfully used to add a web app to homescreen to kick off an |
| // asynchronous fetch of a splash screen icon. Not used on desktop platforms. |
| virtual base::Closure FetchWebappSplashScreenImageCallback( |
| const std::string& webapp_id); |
| |
| protected: |
| explicit AppBannerManager(content::WebContents* web_contents); |
| ~AppBannerManager() override; |
| |
| // Return a string identifying this app for metrics. |
| virtual std::string GetAppIdentifier(); |
| |
| // Return a string describing what type of banner is being created. Used when |
| // alerting websites that a banner is about to be created. |
| virtual std::string GetBannerType(); |
| |
| // Returns a string parameter for a devtools console message corresponding to |
| // |code|. Returns the empty string if |code| requires no parameter. |
| std::string GetStatusParam(InstallableStatusCode code); |
| |
| // Returns the ideal and minimum icon sizes required for being installable. |
| virtual int GetIdealIconSizeInDp(); |
| virtual int GetMinimumIconSizeInDp(); |
| |
| // Returns a WeakPtr to this object. Exposed so subclasses/infobars may |
| // may bind callbacks without needing their own WeakPtrFactory. |
| base::WeakPtr<AppBannerManager> GetWeakPtr(); |
| |
| // Returns true if |is_debug_mode_| is true or the |
| // kBypassAppBannerEngagementChecks flag is set. |
| virtual bool IsDebugMode() const; |
| |
| // Returns true if the webapp at |start_url| has already been installed. |
| virtual bool IsWebAppInstalled(content::BrowserContext* browser_context, |
| const GURL& start_url); |
| |
| // Callback invoked by the InstallableManager once it has fetched the page's |
| // manifest. |
| void OnDidGetManifest(const InstallableData& result); |
| |
| // Run at the conclusion of OnDidGetManifest. For web app banners, this calls |
| // back to the InstallableManager to continue checking criteria. For native |
| // app banners, this checks whether native apps are preferred in the manifest, |
| // and calls to Java to verify native app details. If a native banner isn't or |
| // can't be requested, it continues with the web app banner checks. |
| virtual void PerformInstallableCheck(); |
| |
| // Callback invoked by the InstallableManager once it has finished checking |
| // all other installable properties. |
| void OnDidPerformInstallableCheck(const InstallableData& result); |
| |
| // Records that a banner was shown. The |event_name| corresponds to the RAPPOR |
| // metric being recorded. |
| void RecordDidShowBanner(const std::string& event_name); |
| |
| // Logs an error message corresponding to |code| to the devtools console |
| // attached to |web_contents|. Does nothing if IsDebugMode() returns false. |
| void ReportStatus(content::WebContents* web_contents, |
| InstallableStatusCode code); |
| |
| // Stops the banner pipeline, preventing any outstanding callbacks from |
| // running and resetting the manager state. This method is virtual to allow |
| // tests to intercept it and verify correct behaviour. |
| virtual void Stop(); |
| |
| // Sends a message to the renderer that the page has met the requirements to |
| // show a banner. The page can respond to cancel the banner (and possibly |
| // display it later), or otherwise allow it to be shown. This is virtual to |
| // allow tests to mock out the renderer IPC. |
| virtual void SendBannerPromptRequest(); |
| |
| // content::WebContentsObserver overrides. |
| void DidStartNavigation(content::NavigationHandle* handle) override; |
| void DidFinishNavigation(content::NavigationHandle* handle) override; |
| void DidFinishLoad(content::RenderFrameHost* render_frame_host, |
| const GURL& validated_url) override; |
| void MediaStartedPlaying(const MediaPlayerInfo& media_info, |
| const MediaPlayerId& id) override; |
| void MediaStoppedPlaying(const MediaPlayerInfo& media_info, |
| const MediaPlayerId& id) override; |
| void WebContentsDestroyed() override; |
| |
| // SiteEngagementObserver overrides. |
| void OnEngagementIncreased(content::WebContents* web_contents, |
| const GURL& url, |
| double score) override; |
| |
| // Subclass accessors for private fields which should not be changed outside |
| // this class. |
| InstallableManager* manager() const { return manager_; } |
| int event_request_id() const { return event_request_id_; } |
| bool is_active() const { return is_active_; } |
| |
| // The title to display in the banner. |
| base::string16 app_title_; |
| |
| // The URL for which the banner check is being conducted. |
| GURL validated_url_; |
| |
| // The URL of the manifest. |
| GURL manifest_url_; |
| |
| // The manifest object. |
| content::Manifest manifest_; |
| |
| // The URL of the icon. |
| GURL icon_url_; |
| |
| // The icon object. |
| std::unique_ptr<SkBitmap> icon_; |
| |
| // The referrer string (if any) specified in the app URL. Used only for native |
| // app banners. |
| std::string referrer_; |
| |
| private: |
| friend class AppBannerManagerTest; |
| |
| // Record that the banner could be shown at this point, if the triggering |
| // heuristic allowed. |
| void RecordCouldShowBanner(); |
| |
| // Creates a banner for the app. Overridden by subclasses as the infobar is |
| // platform-specific. |
| virtual void ShowBanner() = 0; |
| |
| // Returns true if the banner should be shown. |
| bool CheckIfShouldShowBanner(); |
| |
| // Called after the manager sends a message to the renderer regarding its |
| // intention to show a prompt. The renderer will send a message back with the |
| // opportunity to cancel. |
| void OnBannerPromptReply(blink::mojom::AppBannerPromptReply reply, |
| const std::string& referrer); |
| |
| // blink::mojom::AppBannerService overrides. |
| // Called when Blink has prevented a banner from being shown, and is now |
| // requesting that it be shown later. |
| void DisplayAppBanner() override; |
| |
| // The type of navigation made to the page |
| ui::PageTransition last_transition_type_; |
| |
| // Fetches the data required to display a banner for the current page. |
| InstallableManager* manager_; |
| |
| // A monotonically increasing id to verify the response to the |
| // beforeinstallprompt event from the renderer. |
| int event_request_id_; |
| |
| // We do not want to trigger a banner when the manager is attached to |
| // a WebContents that is playing video. Banners triggering on a site in the |
| // background will appear when the tab is reactivated. |
| std::vector<MediaPlayerId> active_media_players_; |
| |
| // Mojo bindings and interface pointers. |
| mojo::Binding<blink::mojom::AppBannerService> binding_; |
| blink::mojom::AppBannerEventPtr event_; |
| blink::mojom::AppBannerControllerPtr controller_; |
| |
| // Whether we are currently working on whether to show a banner. |
| bool is_active_; |
| |
| // If a banner is requested before the page has finished loading, defer |
| // triggering the pipeline until the load is complete. |
| bool banner_request_queued_; |
| bool load_finished_; |
| |
| // Record whether the page decides to defer showing the banner, and if it |
| // requests for it to be shown later on. |
| bool was_canceled_by_page_; |
| bool page_requested_prompt_; |
| |
| // Whether we should be logging errors to the console for this request. |
| bool is_debug_mode_; |
| |
| // Whether the installable status has been logged for this run. |
| bool need_to_log_status_; |
| |
| // The concrete subclasses of this class are expected to have their lifetimes |
| // scoped to the WebContents which they are observing. This allows us to use |
| // weak pointers for callbacks. |
| base::WeakPtrFactory<AppBannerManager> weak_factory_; |
| |
| DISALLOW_COPY_AND_ASSIGN(AppBannerManager); |
| }; |
| |
| } // namespace banners |
| |
| #endif // CHROME_BROWSER_BANNERS_APP_BANNER_MANAGER_H_ |