chromium/ios/chrome/browser/push_notification/model/push_notification_client.h

// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef IOS_CHROME_BROWSER_PUSH_NOTIFICATION_MODEL_PUSH_NOTIFICATION_CLIENT_H_
#define IOS_CHROME_BROWSER_PUSH_NOTIFICATION_MODEL_PUSH_NOTIFICATION_CLIENT_H_

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <UserNotifications/UserNotifications.h>

#import <string>

#import "base/memory/raw_ptr.h"
#import "ios/chrome/browser/push_notification/model/push_notification_client_id.h"
#import "ios/chrome/browser/shared/model/profile/profile_ios.h"
#import "url/gurl.h"

class CommercePushNotificationClientTest;

class Browser;

// The PushNotificationClient class is an abstract class that provides a
// framework for implementing push notification support. Feature teams that
// intend to support push notifications should create a class that inherits from
// the PushNotificationClient class.
// TODO(crbug.com/325254943): Update this class and subclasses to accept an
// injected ChromeBrowserState* and not internally fetch a browser state via
// GetlastUsedBrowserState. Update tests as well.
class PushNotificationClient {
 public:
  PushNotificationClient(PushNotificationClientId client_id);
  virtual ~PushNotificationClient() = 0;

  // When the user interacts with a push notification, this function is called
  // to route the user to the appropriate destination.
  virtual void HandleNotificationInteraction(
      UNNotificationResponse* notification_response) = 0;

  // When the device receives a push notification, this function is called to
  // allow the client to process any logic needed at this point in time. The
  // function's return value represents the state of data that the
  // PushNotificationClient fetched.
  virtual UIBackgroundFetchResult HandleNotificationReception(
      NSDictionary<NSString*, id>* user_info) = 0;

  // Actionable Notifications are push notifications that provide the user
  // with predetermined actions that the user can select to manipulate the
  // application without ever entering the application. Actionable
  // notifications must be registered during application startup.
  virtual NSArray<UNNotificationCategory*>*
  RegisterActionableNotifications() = 0;

  // Signals to the client that a browser with scene level
  // SceneActivationLevelForegroundActive is ready. Without this
  // URL opening code driven by push notifications may not be able to
  // access a browser appropriate for opening a URL (active & scene
  // level SceneActivationLevelForegroundActive) resulting in the URL
  // not being opened.
  virtual void OnSceneActiveForegroundBrowserReady();

  // Returns the feature's `client_id_`.
  PushNotificationClientId GetClientId();

  // Loads a url in a new tab once an active browser is ready.
  // TODO(crbug.com/41497027): This API should includes an identifier of the
  // Profile that should be used to open the URL which should come from the
  // notification (maybe by including the gaia id of the associated profile).
  void LoadUrlInNewTab(const GURL& url);

  // Loads the feedback view controller once an active browser is ready.
  // TODO(crbug.com/41497027): This API should includes an identifier of the
  // Profile that should be used to open the URL which should come from the
  // notification (maybe by including the gaia id of the associated profile).
  void LoadFeedbackWithPayloadAndClientId(
      NSDictionary<NSString*, NSString*>* data,
      PushNotificationClientId clientId);

 protected:
  // The unique string that is used to associate incoming push notifications to
  // their destination feature. This identifier must match the identifier
  // used inside the notification's payload when sending the notification to the
  // push notification server.
  PushNotificationClientId client_id_;

  // Returns an arbitrary profile amongst the currently loaded profile. This
  // means that this API is not safe when there are multiple profiles. Instead
  // the push notification system should be re-designed to not depend on this
  // method (either create specific manager per-profile, or include in the
  // notification an identifier for the profile, e.g. gaia id).
  // TODO(crbug.com/41497027): This API should be redesigned.
  ChromeBrowserState* GetAnyProfile();

  // Returns the first active browser found with scene level
  // SceneActivationLevelForegroundActive.
  Browser* GetSceneLevelForegroundActiveBrowser();

 private:
  friend class ::CommercePushNotificationClientTest;
  std::vector<GURL> urls_delayed_for_loading_;

  // Stores whether or not the feedback view controller should be shown when a
  // Browser is ready.
  bool feedback_presentation_delayed_ = false;

  // Stores which client sent the delayed feedback request.
  PushNotificationClientId feedback_presentation_delayed_client_;

  // Stores the feedback payload to be sent with the notification feedback.
  NSDictionary<NSString*, NSString*>* feedback_data_ = nil;

  // Loads a url in a new tab for a given browser.
  void LoadUrlInNewTab(const GURL& url, Browser* browser);
};

#endif  // IOS_CHROME_BROWSER_PUSH_NOTIFICATION_MODEL_PUSH_NOTIFICATION_CLIENT_H_