chromium/ios/web/js_messaging/web_frames_manager_java_script_feature.h

// Copyright 2021 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_WEB_JS_MESSAGING_WEB_FRAMES_MANAGER_JAVA_SCRIPT_FEATURE_H_
#define IOS_WEB_JS_MESSAGING_WEB_FRAMES_MANAGER_JAVA_SCRIPT_FEATURE_H_

#import <WebKit/WebKit.h>

#import "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/supports_user_data.h"
#import "ios/web/js_messaging/scoped_wk_script_message_handler.h"
#import "ios/web/public/js_messaging/java_script_feature.h"

namespace web {
class BrowserState;

// A feature which notifies the native application code of the creation and
// destruction of webpage frames based on JavaScript messages from the webpage.
class WebFramesManagerJavaScriptFeature : public JavaScriptFeature {
 public:
  ~WebFramesManagerJavaScriptFeature() override;

  WebFramesManagerJavaScriptFeature(const WebFramesManagerJavaScriptFeature&) =
      delete;
  WebFramesManagerJavaScriptFeature& operator=(
      const WebFramesManagerJavaScriptFeature&) = delete;

  // Returns a list of the `WebFramesManagerJavaScriptFeature` instances for
  // all content worlds specified by `browser_state`s' JavaScriptFeatureManager.
  static std::vector<WebFramesManagerJavaScriptFeature*>
  AllContentWorldFeaturesFromBrowserState(BrowserState* browser_state);

  // Configures message handlers for the creation and destruction of frames.
  // `user_content_controller` is used directly (instead of using the built-in
  // JavaScriptFeature message handling) because constructing WebFrame instances
  // requires access to the WKScriptMessage's WKFrameInfo instance.
  void ConfigureHandlers(WKUserContentController* user_content_controller);

 private:
  // Container that stores the web frame manager feature for each content world.
  // Usage example:
  //
  // WebFramesManagerJavaScriptFeature::Container::FromBrowserState(
  //     browser_state)->FeatureForContentWorld(
  //         ContentWorld::kPageContentWorld);
  class Container : public base::SupportsUserData::Data {
   public:
    ~Container() override;

    // Returns the Container associated with `browser_state`, creating one if
    // necessary. `browser_state` must not be null.
    static Container* FromBrowserState(BrowserState* browser_state);

    // Returns the web frames manager feature for `content_world`.
    WebFramesManagerJavaScriptFeature* FeatureForContentWorld(
        ContentWorld content_world);

   private:
    Container(BrowserState* browser_state);

    // The browser state associated with this instance of the feature.
    raw_ptr<BrowserState> browser_state_;
    std::map<ContentWorld, std::unique_ptr<WebFramesManagerJavaScriptFeature>>
        features_;
  };

  friend class WebFramesManagerJavaScriptFeatureTest;

  WebFramesManagerJavaScriptFeature(ContentWorld content_world,
                                    BrowserState* browser_state);

  // Handles a message from JavaScript to register a new WebFrame.
  void FrameAvailableMessageReceived(WKScriptMessage* script_message);
  // Handles a message from JavaScript to remove a WebFrame.
  void FrameUnavailableMessageReceived(WKScriptMessage* script_message);

  // The content world which this web frames manager operates in.
  ContentWorld content_world_;
  // The browser state associated with this instance of the feature.
  raw_ptr<BrowserState> browser_state_;

  // This feature uses ScopedWKScriptMessageHandler directly instead of the
  // message handling built into JavaScriptFeature because creating WebFrames
  // requires a pointer to the WKFrameInfo object (which is intentionally hidden
  // from JavaScriptFeature::ScriptMessageReceived).
  std::unique_ptr<ScopedWKScriptMessageHandler> frame_available_handler_;
  std::unique_ptr<ScopedWKScriptMessageHandler> frame_unavailable_handler_;

  base::WeakPtrFactory<WebFramesManagerJavaScriptFeature> weak_factory_;
};

}  // namespace web

#endif  // IOS_WEB_JS_MESSAGING_WEB_FRAMES_MANAGER_JAVA_SCRIPT_FEATURE_H_