chromium/ios/web/js_messaging/java_script_feature_manager.mm

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

#import "ios/web/js_messaging/java_script_feature_manager.h"

#import <WebKit/WebKit.h>

#import "base/ios/ios_util.h"
#import "ios/web/public/browser_state.h"
#import "ios/web/public/js_messaging/content_world.h"
#import "ios/web/public/js_messaging/java_script_feature.h"
#import "ios/web/public/js_messaging/java_script_feature_util.h"

namespace {

// Key used to associate a JavaScriptFeatureManager instances with a
// BrowserState.
const char kWebJavaScriptFeatureManagerKeyName[] =
    "web_java_script_feature_manager";

}  // namespace

namespace web {

JavaScriptFeatureManager::JavaScriptFeatureManager(BrowserState* browser_state)
    : browser_state_(browser_state) {}
JavaScriptFeatureManager::~JavaScriptFeatureManager() {}

JavaScriptFeatureManager* JavaScriptFeatureManager::FromBrowserState(
    BrowserState* browser_state) {
  DCHECK(browser_state);

  JavaScriptFeatureManager* feature_manager =
      static_cast<JavaScriptFeatureManager*>(
          browser_state->GetUserData(kWebJavaScriptFeatureManagerKeyName));
  if (!feature_manager) {
    feature_manager = new JavaScriptFeatureManager(browser_state);
    browser_state->SetUserData(kWebJavaScriptFeatureManagerKeyName,
                               base::WrapUnique(feature_manager));
  }
  return feature_manager;
}

JavaScriptContentWorld*
JavaScriptFeatureManager::GetPageContentWorldForBrowserState(
    BrowserState* browser_state) {
  DCHECK(browser_state);
  JavaScriptFeatureManager* feature_manager = FromBrowserState(browser_state);
  return feature_manager->page_content_world_.get();
}

void JavaScriptFeatureManager::ConfigureFeatures(
    std::vector<JavaScriptFeature*> features) {
  page_content_world_ = std::make_unique<JavaScriptContentWorld>(
      browser_state_, WKContentWorld.pageWorld);

  isolated_world_ = std::make_unique<JavaScriptContentWorld>(
      browser_state_, WKContentWorld.defaultClientWorld);

  for (JavaScriptFeature* feature : features) {
    switch (feature->GetSupportedContentWorld()) {
      case ContentWorld::kAllContentWorlds:
        isolated_world_->AddFeature(feature);
        page_content_world_->AddFeature(feature);
        break;
      case ContentWorld::kIsolatedWorld:
        isolated_world_->AddFeature(feature);
        break;
      case ContentWorld::kPageContentWorld:
        page_content_world_->AddFeature(feature);
        break;
    }
  }
}

JavaScriptContentWorld* JavaScriptFeatureManager::GetContentWorldForFeature(
    JavaScriptFeature* feature) {
  if (isolated_world_->HasFeature(feature)) {
    return isolated_world_.get();
  }
  if (page_content_world_->HasFeature(feature)) {
    return page_content_world_.get();
  }
  return nullptr;
}

std::vector<JavaScriptContentWorld*>
JavaScriptFeatureManager::GetAllContentWorlds() {
  return {isolated_world_.get(), page_content_world_.get()};
}

std::vector<ContentWorld> JavaScriptFeatureManager::GetAllContentWorldEnums() {
  // Return these from WKContentWorld directly instead of from
  // JavaScriptContentWorld instances because JavaScriptContentWorld are not
  // created until after `ConfigureFeatures`.
  return {ContentWorld::kPageContentWorld, ContentWorld::kIsolatedWorld};
}

}  // namespace web