diff --git a/ios/web/js_messaging/BUILD.gn b/ios/web/js_messaging/BUILD.gn index 0be0e5343e866c..0181a9f25e444b 100644 --- a/ios/web/js_messaging/BUILD.gn +++ b/ios/web/js_messaging/BUILD.gn @@ -10,6 +10,7 @@ source_set("js_messaging") { deps = [ ":frame_listeners_js", ":java_script_content_world_header", + ":java_script_feature_manager_header", ":scoped_wk_script_message_handler", ":setup_frame_js", ":web_frames_manager_impl_header", @@ -58,7 +59,10 @@ source_set("web_frames_manager_impl_header") { source_set("java_script_feature") { configs += [ "//build/config/compiler:enable_arc" ] - public_deps = [ ":java_script_content_world_header" ] + public_deps = [ + ":java_script_content_world_header", + ":java_script_feature_manager_header", + ] deps = [ ":js_messaging", ":scoped_wk_script_message_handler", @@ -73,7 +77,6 @@ source_set("java_script_feature") { sources = [ "java_script_content_world.mm", "java_script_feature.mm", - "java_script_feature_manager.h", "java_script_feature_manager.mm", "script_message.mm", ] @@ -91,6 +94,17 @@ source_set("java_script_content_world_header") { sources = [ "java_script_content_world.h" ] } +source_set("java_script_feature_manager_header") { + configs += [ "//build/config/compiler:enable_arc" ] + + deps = [ + ":java_script_content_world_header", + "//base", + ] + + sources = [ "java_script_feature_manager.h" ] +} + source_set("java_script_feature_util") { configs += [ "//build/config/compiler:enable_arc" ] diff --git a/ios/web/js_messaging/java_script_content_world.h b/ios/web/js_messaging/java_script_content_world.h index 6a9c1bf579f057..09385b7e1cb4d9 100644 --- a/ios/web/js_messaging/java_script_content_world.h +++ b/ios/web/js_messaging/java_script_content_world.h @@ -33,10 +33,6 @@ class JavaScriptContentWorld { ~JavaScriptContentWorld(); JavaScriptContentWorld(const JavaScriptContentWorld&) = delete; - // Creates a content world for features which will interact with the page - // content world shared by the webpage's JavaScript. - explicit JavaScriptContentWorld(BrowserState* browser_state); - // Creates a content world for features which will interact with the given // |content_world|. JavaScriptContentWorld(BrowserState* browser_state, diff --git a/ios/web/js_messaging/java_script_content_world.mm b/ios/web/js_messaging/java_script_content_world.mm index d103f7e35d42d8..d59ba84b4196f1 100644 --- a/ios/web/js_messaging/java_script_content_world.mm +++ b/ios/web/js_messaging/java_script_content_world.mm @@ -53,11 +53,6 @@ WKUserScriptInjectionTime InjectionTimeToWKUserScriptInjectionTime( } // namespace -JavaScriptContentWorld::JavaScriptContentWorld(BrowserState* browser_state) - : browser_state_(browser_state), - user_content_controller_(GetUserContentController(browser_state)), - weak_factory_(this) {} - #if defined(__IPHONE_14_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0 JavaScriptContentWorld::JavaScriptContentWorld(BrowserState* browser_state, WKContentWorld* content_world) diff --git a/ios/web/js_messaging/java_script_content_world_unittest.mm b/ios/web/js_messaging/java_script_content_world_unittest.mm index f147c32b3b2573..c6b3df493bdc81 100644 --- a/ios/web/js_messaging/java_script_content_world_unittest.mm +++ b/ios/web/js_messaging/java_script_content_world_unittest.mm @@ -30,13 +30,14 @@ [[user_content_controller userScripts] count]; ASSERT_GT(initial_scripts_count, 0ul); - web::JavaScriptContentWorld world(GetBrowserState()); + web::JavaScriptContentWorld world(GetBrowserState(), + WKContentWorld.pageWorld); FakeJavaScriptFeature feature( JavaScriptFeature::ContentWorld::kAnyContentWorld); world.AddFeature(&feature); EXPECT_TRUE(world.HasFeature(&feature)); - EXPECT_FALSE(world.GetWKContentWorld()); + EXPECT_EQ(WKContentWorld.pageWorld, world.GetWKContentWorld()); unsigned long scripts_count = [[user_content_controller userScripts] count]; ASSERT_GT(scripts_count, initial_scripts_count); @@ -54,14 +55,14 @@ FakeJavaScriptFeature feature( ASSERT_GT(initial_scripts_count, 0ul); web::JavaScriptContentWorld world(GetBrowserState(), - [WKContentWorld defaultClientWorld]); + WKContentWorld.defaultClientWorld); FakeJavaScriptFeature feature( JavaScriptFeature::ContentWorld::kAnyContentWorld); world.AddFeature(&feature); EXPECT_TRUE(world.HasFeature(&feature)); - EXPECT_EQ([WKContentWorld defaultClientWorld], world.GetWKContentWorld()); + EXPECT_EQ(WKContentWorld.defaultClientWorld, world.GetWKContentWorld()); unsigned long scripts_count = [[user_content_controller userScripts] count]; ASSERT_GT(scripts_count, initial_scripts_count); @@ -79,14 +80,14 @@ FakeJavaScriptFeature feature( ASSERT_GT(initial_scripts_count, 0ul); web::JavaScriptContentWorld world(GetBrowserState(), - [WKContentWorld defaultClientWorld]); + WKContentWorld.defaultClientWorld); FakeJavaScriptFeature feature( JavaScriptFeature::ContentWorld::kIsolatedWorldOnly); world.AddFeature(&feature); EXPECT_TRUE(world.HasFeature(&feature)); - EXPECT_EQ([WKContentWorld defaultClientWorld], world.GetWKContentWorld()); + EXPECT_EQ(WKContentWorld.defaultClientWorld, world.GetWKContentWorld()); unsigned long scripts_count = [[user_content_controller userScripts] count]; ASSERT_GT(scripts_count, initial_scripts_count); @@ -96,7 +97,7 @@ FakeJavaScriptFeature feature( // content world triggers a DCHECK. TEST_F(JavaScriptContentWorldTest, AddIsolatedWorldFeatureToPageWorld) { web::JavaScriptContentWorld world(GetBrowserState(), - [WKContentWorld pageWorld]); + WKContentWorld.pageWorld); FakeJavaScriptFeature feature( JavaScriptFeature::ContentWorld::kIsolatedWorldOnly); diff --git a/ios/web/js_messaging/java_script_feature_manager.h b/ios/web/js_messaging/java_script_feature_manager.h index e8bb8d84e2323b..b76c8a0f0eaf84 100644 --- a/ios/web/js_messaging/java_script_feature_manager.h +++ b/ios/web/js_messaging/java_script_feature_manager.h @@ -32,6 +32,13 @@ class JavaScriptFeatureManager : public base::SupportsUserData::Data { static JavaScriptFeatureManager* FromBrowserState( BrowserState* browser_state); + // Returns the JavaScriptContentWorld for the page content world associated + // with |browser_state|. If a JavaScriptFeatureManager does not already exist, + // one will be created and associated with |browser_state|. |browser_state| + // must not be null. + static JavaScriptContentWorld* GetPageContentWorldForBrowserState( + BrowserState* browser_state); + // Configures |features| on |user_content_controller_| by adding user scripts // and script message handlers. // NOTE: |page_content_world_| and |isolated_world_| will be recreated. diff --git a/ios/web/js_messaging/java_script_feature_manager.mm b/ios/web/js_messaging/java_script_feature_manager.mm index 3effbbbb48cf90..c5b7eaa106dac8 100644 --- a/ios/web/js_messaging/java_script_feature_manager.mm +++ b/ios/web/js_messaging/java_script_feature_manager.mm @@ -58,10 +58,18 @@ void AddSharedCommonFeatures(web::JavaScriptContentWorld* world) { 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 features) { - page_content_world_ = - std::make_unique(browser_state_); + page_content_world_ = std::make_unique( + browser_state_, WKContentWorld.pageWorld); AddSharedCommonFeatures(page_content_world_.get()); isolated_world_ = std::make_unique( diff --git a/ios/web/js_messaging/web_frame_impl.mm b/ios/web/js_messaging/web_frame_impl.mm index 10bc355dfb371d..34f8e8f048ab1a 100644 --- a/ios/web/js_messaging/web_frame_impl.mm +++ b/ios/web/js_messaging/web_frame_impl.mm @@ -20,6 +20,7 @@ #include "crypto/aead.h" #include "crypto/random.h" #import "ios/web/js_messaging/java_script_content_world.h" +#import "ios/web/js_messaging/java_script_feature_manager.h" #import "ios/web/js_messaging/web_view_js_utils.h" #include "ios/web/public/thread/web_task_traits.h" #include "ios/web/public/thread/web_thread.h" @@ -114,7 +115,7 @@ // because calling the function directly on the webstate with // |ExecuteJavaScript| is secure. However, iframes require an encryption key // in order to securely pass the function name and parameters to the frame. - return is_main_frame_ || frame_key_; + return is_main_frame_ || frame_key_ || frame_info_; } BrowserState* WebFrameImpl::GetBrowserState() { @@ -173,6 +174,11 @@ reply_with_result); } + // There should always be a content_world now and + // `__gCrWeb.message.routeMessage` calls shouldn't be necessary. + // TODO(crbug.com/1339441): Remove custom iFrame messaging system. + NOTREACHED(); + base::Value message_payload(base::Value::Type::DICTIONARY); message_payload.SetKey("messageId", base::Value(message_id)); message_payload.SetKey("replyWithResult", base::Value(reply_with_result)); @@ -203,8 +209,11 @@ bool WebFrameImpl::CallJavaScriptFunction( const std::string& name, const std::vector& parameters) { - return CallJavaScriptFunctionInContentWorld(name, parameters, - /*content_world=*/nullptr, + JavaScriptContentWorld* content_world = + JavaScriptFeatureManager::GetPageContentWorldForBrowserState( + GetBrowserState()); + + return CallJavaScriptFunctionInContentWorld(name, parameters, content_world, /*reply_with_result=*/false); } @@ -221,8 +230,10 @@ const std::vector& parameters, base::OnceCallback callback, base::TimeDelta timeout) { - return CallJavaScriptFunctionInContentWorld(name, parameters, - /*content_world=*/nullptr, + JavaScriptContentWorld* content_world = + JavaScriptFeatureManager::GetPageContentWorldForBrowserState( + GetBrowserState()); + return CallJavaScriptFunctionInContentWorld(name, parameters, content_world, std::move(callback), timeout); } diff --git a/ios/web/js_messaging/web_frame_impl_unittest.mm b/ios/web/js_messaging/web_frame_impl_unittest.mm index 9db06c7e27f0b8..d6fe93a24078c1 100644 --- a/ios/web/js_messaging/web_frame_impl_unittest.mm +++ b/ios/web/js_messaging/web_frame_impl_unittest.mm @@ -41,51 +41,6 @@ decoded_frame_key_string); } -struct RouteMessageParameters { - NSString* encoded_message_payload = nil; - NSString* encoded_message_iv = nil; - NSString* encoded_function_payload = nil; - NSString* encoded_function_iv = nil; - NSString* frame_id = nil; -}; - -RouteMessageParameters ParametersFromFunctionCallString( - NSString* function_call) { - NSRange parameters_start = [function_call rangeOfString:@"("]; - NSRange parameters_end = [function_call rangeOfString:@")"]; - NSMutableString* parameter_string = [[function_call - substringWithRange:NSMakeRange(parameters_start.location + 1, - parameters_end.location - - parameters_start.location - 1)] - mutableCopy]; - // Create array string and replace single quotes with double quotes in - // preparation for JSON serialization. - [parameter_string insertString:@"[" atIndex:0]; - [parameter_string appendString:@"]"]; - NSString* final_string = - [parameter_string stringByReplacingOccurrencesOfString:@"'" - withString:@"\""]; - - NSData* data = [final_string dataUsingEncoding:NSUTF8StringEncoding]; - NSError* error = nil; - NSArray* jsonArray = - [NSJSONSerialization JSONObjectWithData:data - options:NSJSONReadingMutableContainers | - NSJSONReadingMutableLeaves - error:&error]; - - RouteMessageParameters parsed_params; - if (jsonArray.count == 3 && !error) { - parsed_params.encoded_message_iv = jsonArray[0][@"iv"]; - parsed_params.encoded_message_payload = jsonArray[0][@"payload"]; - parsed_params.encoded_function_iv = jsonArray[1][@"iv"]; - parsed_params.encoded_function_payload = jsonArray[1][@"payload"]; - parsed_params.frame_id = jsonArray[2]; - } - - return parsed_params; -} - } // namespace namespace web { @@ -123,22 +78,6 @@ WebFrameImpl web_frame([[WKFrameInfo alloc] init], kFrameId, EXPECT_EQ(kFrameId, web_frame.GetFrameId()); } -// Tests creation of a WebFrame for a frame which is not the main frame without -// an encryption key. -TEST_F(WebFrameImplTest, CreateWebFrameForIFrame) { - FakeWebState fake_web_state; - GURL security_origin; - WebFrameImpl web_frame([[WKFrameInfo alloc] init], kFrameId, - /*is_main_frame=*/false, security_origin, - &fake_web_state); - - EXPECT_EQ(&fake_web_state, web_frame.GetWebState()); - EXPECT_FALSE(web_frame.IsMainFrame()); - EXPECT_FALSE(web_frame.CanCallJavaScriptFunction()); - EXPECT_EQ(security_origin, web_frame.GetSecurityOrigin()); - EXPECT_EQ(kFrameId, web_frame.GetFrameId()); -} - // Tests creation of a WebFrame for a frame which is not the main frame with an // encryption key. TEST_F(WebFrameImplTest, CreateWebFrameForIFrameWithKey) { @@ -156,250 +95,11 @@ WebFrameImpl web_frame([[WKFrameInfo alloc] init], kFrameId, EXPECT_EQ(kFrameId, web_frame.GetFrameId()); } -// Tests that |CallJavaScriptFunction| encrypts the message and passes it to -// __gCrWeb.message.routeMessage in the main frame. -TEST_F(WebFrameImplTest, CallJavaScriptFunction) { - FakeWebState fake_web_state; - GURL security_origin; - WebFrameImpl web_frame([[WKFrameInfo alloc] init], kFrameId, - /*is_main_frame=*/false, security_origin, - &fake_web_state); - web_frame.SetEncryptionKey(CreateKey()); - - std::vector function_params; - function_params.push_back(base::Value("plaintextParam")); - EXPECT_TRUE( - web_frame.CallJavaScriptFunction("functionName", function_params)); - - NSString* last_script = - base::SysUTF16ToNSString(fake_web_state.GetLastExecutedJavascript()); - EXPECT_TRUE([last_script hasPrefix:@"__gCrWeb.message.routeMessage"]); - // Verify the message does not contain the plaintext function name or - // parameters. - EXPECT_FALSE([last_script containsString:@"functionName"]); - EXPECT_FALSE([last_script containsString:@"plaintextParam"]); - - RouteMessageParameters params = ParametersFromFunctionCallString(last_script); - - // Verify that the message and function payload are properly base64 encoded - // strings. - std::string decoded_function_payload; - EXPECT_TRUE(base::Base64Decode( - base::SysNSStringToUTF8(params.encoded_function_payload), - &decoded_function_payload)); - std::string decoded_message_payload; - EXPECT_TRUE(base::Base64Decode( - base::SysNSStringToUTF8(params.encoded_message_payload), - &decoded_message_payload)); - // Verify the function does not contain the plaintext function name or - // parameters. - EXPECT_FALSE([base::SysUTF8ToNSString(decoded_function_payload) - containsString:@"functionName"]); - EXPECT_FALSE([base::SysUTF8ToNSString(decoded_function_payload) - containsString:@"plaintextParam"]); - - // Verify that the initialization vector is a properly base64 encoded string - // for both payloads. - std::string function_iv_string = - base::SysNSStringToUTF8(params.encoded_function_iv); - std::string decoded_function_iv; - EXPECT_TRUE(base::Base64Decode(function_iv_string, &decoded_function_iv)); - std::string message_iv_string = - base::SysNSStringToUTF8(params.encoded_message_iv); - std::string decoded_message_iv; - EXPECT_TRUE(base::Base64Decode(message_iv_string, &decoded_message_iv)); - - // Ensure the frame ID matches. - EXPECT_NSEQ(base::SysUTF8ToNSString(kFrameId), params.frame_id); -} - -// Tests that the WebFrame uses different initialization vectors for two -// sequential calls to |CallJavaScriptFunction|. -TEST_F(WebFrameImplTest, CallJavaScriptFunctionUniqueInitializationVector) { - FakeWebState fake_web_state; - GURL security_origin; - WebFrameImpl web_frame([[WKFrameInfo alloc] init], kFrameId, - /*is_main_frame=*/false, security_origin, - &fake_web_state); - web_frame.SetEncryptionKey(CreateKey()); - - std::vector function_params; - function_params.push_back(base::Value("plaintextParam")); - EXPECT_TRUE( - web_frame.CallJavaScriptFunction("functionName", function_params)); - - NSString* last_script1 = - base::SysUTF16ToNSString(fake_web_state.GetLastExecutedJavascript()); - RouteMessageParameters params1 = - ParametersFromFunctionCallString(last_script1); - - // Call JavaScript Function again to verify that the same initialization - // vector is not reused and that the ciphertext is different. - EXPECT_TRUE( - web_frame.CallJavaScriptFunction("functionName", function_params)); - NSString* last_script2 = - base::SysUTF16ToNSString(fake_web_state.GetLastExecutedJavascript()); - RouteMessageParameters params2 = - ParametersFromFunctionCallString(last_script2); - - EXPECT_NSNE(params1.encoded_function_payload, - params2.encoded_function_payload); - EXPECT_NSNE(params1.encoded_function_iv, params2.encoded_function_iv); -} - -// Tests that the WebFrame properly encodes and encrypts all parameters for -// |CallJavaScriptFunction|. -TEST_F(WebFrameImplTest, CallJavaScriptFunctionMessageProperlyEncoded) { - std::unique_ptr key = CreateKey(); - const std::string key_string = key->key(); - // Use an arbitrary nonzero message id to ensure it isn't matching a zero - // value by chance. - const int initial_message_id = 11; - - FakeWebState fake_web_state; - GURL security_origin; - WebFrameImpl web_frame([[WKFrameInfo alloc] init], kFrameId, - /*is_main_frame=*/false, security_origin, - &fake_web_state); - web_frame.SetEncryptionKey(std::move(key)); - web_frame.SetNextMessageId(initial_message_id); - - std::vector function_params; - std::string plaintext_param("plaintextParam"); - function_params.push_back(base::Value(plaintext_param)); - EXPECT_TRUE( - web_frame.CallJavaScriptFunction("functionName", function_params)); - - NSString* last_script = - base::SysUTF16ToNSString(fake_web_state.GetLastExecutedJavascript()); - RouteMessageParameters params = ParametersFromFunctionCallString(last_script); - - std::string decoded_function_ciphertext; - EXPECT_TRUE(base::Base64Decode( - base::SysNSStringToUTF8(params.encoded_function_payload), - &decoded_function_ciphertext)); - - std::string decoded_function_iv; - EXPECT_TRUE( - base::Base64Decode(base::SysNSStringToUTF8(params.encoded_function_iv), - &decoded_function_iv)); - - std::string decoded_message_ciphertext; - EXPECT_TRUE(base::Base64Decode( - base::SysNSStringToUTF8(params.encoded_message_payload), - &decoded_message_ciphertext)); - - std::string decoded_message_iv; - EXPECT_TRUE(base::Base64Decode( - base::SysNSStringToUTF8(params.encoded_message_iv), &decoded_message_iv)); - - // Decrypt message - crypto::Aead aead(crypto::Aead::AES_256_GCM); - aead.Init(&key_string); - std::string function_plaintext; - EXPECT_TRUE(aead.Open(decoded_function_ciphertext, decoded_function_iv, - base::NumberToString(initial_message_id), - &function_plaintext)); - std::string message_plaintext; - EXPECT_TRUE(aead.Open(decoded_message_ciphertext, decoded_message_iv, - /*additional_data=*/"", &message_plaintext)); - - absl::optional parsed_function_result = - base::JSONReader::Read(function_plaintext, false); - EXPECT_TRUE(parsed_function_result.has_value()); - ASSERT_TRUE(parsed_function_result.value().is_dict()); - - const std::string* decrypted_function_name = - parsed_function_result.value().FindStringKey("functionName"); - ASSERT_TRUE(decrypted_function_name); - EXPECT_EQ("functionName", *decrypted_function_name); - - base::Value* decrypted_parameters = - parsed_function_result.value().FindKeyOfType("parameters", - base::Value::Type::LIST); - ASSERT_TRUE(decrypted_parameters); - ASSERT_EQ(function_params.size(), - decrypted_parameters->GetListDeprecated().size()); - EXPECT_EQ(plaintext_param, - decrypted_parameters->GetListDeprecated()[0].GetString()); - - absl::optional parsed_message_result = - base::JSONReader::Read(message_plaintext, false); - EXPECT_TRUE(parsed_message_result.has_value()); - ASSERT_TRUE(parsed_message_result.value().is_dict()); - - absl::optional decrypted_message_id = - parsed_message_result.value().FindIntKey("messageId"); - ASSERT_TRUE(decrypted_message_id.has_value()); - EXPECT_EQ(decrypted_message_id.value(), initial_message_id); - - absl::optional decrypted_respond_with_result = - parsed_message_result.value().FindBoolKey("replyWithResult"); - ASSERT_TRUE(decrypted_respond_with_result.has_value()); - EXPECT_FALSE(decrypted_respond_with_result.value()); -} - -// Tests that the WebFrame properly encodes and encrypts the respondWithResult -// value when |CallJavaScriptFunction| is called with a callback. -TEST_F(WebFrameImplTest, CallJavaScriptFunctionRespondWithResult) { - std::unique_ptr key = CreateKey(); - const std::string key_string = key->key(); - // Use an arbitrary nonzero message id to ensure it isn't matching a zero - // value by chance. - const int initial_message_id = 11; - - FakeWebState fake_web_state; - GURL security_origin; - WebFrameImpl web_frame([[WKFrameInfo alloc] init], kFrameId, - /*is_main_frame=*/false, security_origin, - &fake_web_state); - web_frame.SetEncryptionKey(std::move(key)); - web_frame.SetNextMessageId(initial_message_id); - - std::vector function_params; - std::string plaintext_param("plaintextParam"); - function_params.push_back(base::Value(plaintext_param)); - EXPECT_TRUE(web_frame.CallJavaScriptFunction( - "functionName", function_params, - base::BindOnce(^(const base::Value* value){ - }), - base::Seconds(5))); - - NSString* last_script = - base::SysUTF16ToNSString(fake_web_state.GetLastExecutedJavascript()); - RouteMessageParameters params = ParametersFromFunctionCallString(last_script); - - std::string decoded_message_ciphertext; - EXPECT_TRUE(base::Base64Decode( - base::SysNSStringToUTF8(params.encoded_message_payload), - &decoded_message_ciphertext)); - - std::string decoded_message_iv; - EXPECT_TRUE(base::Base64Decode( - base::SysNSStringToUTF8(params.encoded_message_iv), &decoded_message_iv)); - - // Decrypt message - crypto::Aead aead(crypto::Aead::AES_256_GCM); - aead.Init(&key_string); - std::string message_plaintext; - EXPECT_TRUE(aead.Open(decoded_message_ciphertext, decoded_message_iv, - /*additional_data=*/"", &message_plaintext)); - - absl::optional parsed_result = - base::JSONReader::Read(message_plaintext, false); - EXPECT_TRUE(parsed_result.has_value()); - ASSERT_TRUE(parsed_result.value().is_dict()); - - absl::optional decrypted_respond_with_result = - parsed_result.value().FindBoolKey("replyWithResult"); - ASSERT_TRUE(decrypted_respond_with_result.has_value()); - EXPECT_TRUE(decrypted_respond_with_result.value()); -} - // Tests that the WebFrame properly creates JavaScript for the main frame when // there is no encryption key. TEST_F(WebFrameImplTest, CallJavaScriptFunctionMainFrameWithoutKey) { FakeWebState fake_web_state; + fake_web_state.SetBrowserState(GetBrowserState()); GURL security_origin; WebFrameImpl web_frame([[WKFrameInfo alloc] init], kFrameId, /*is_main_frame=*/true, security_origin, @@ -434,6 +134,7 @@ WebFrameImpl web_frame([[WKFrameInfo alloc] init], kFrameId, // is no encryption key. TEST_F(WebFrameImplTest, CallJavaScriptFunctionIFrameFrameWithoutKey) { FakeWebState fake_web_state; + fake_web_state.SetBrowserState(GetBrowserState()); GURL security_origin; WebFrameImpl web_frame([[WKFrameInfo alloc] init], kFrameId, /*is_main_frame=*/false, security_origin, @@ -453,6 +154,7 @@ WebFrameImpl web_frame([[WKFrameInfo alloc] init], kFrameId, // if and only if it is a main frame. TEST_F(WebFrameImplTest, ExecuteJavaScript) { FakeWebState fake_web_state; + fake_web_state.SetBrowserState(GetBrowserState()); GURL security_origin; NSString* script = @"__gCrWeb = {};" @@ -477,6 +179,8 @@ WebFrameImpl web_frame2([[WKFrameInfo alloc] init], kFrameId, // a callback if and only if it is a main frame. TEST_F(WebFrameImplTest, ExecuteJavaScriptWithCallback) { FakeWebState fake_web_state; + fake_web_state.SetBrowserState(GetBrowserState()); + GURL security_origin; NSString* script = @"__gCrWeb = {};" diff --git a/ios/web/public/test/web_view_interaction_test_util.mm b/ios/web/public/test/web_view_interaction_test_util.mm index aaf45289710ca5..39e25713f49361 100644 --- a/ios/web/public/test/web_view_interaction_test_util.mm +++ b/ios/web/public/test/web_view_interaction_test_util.mm @@ -102,6 +102,9 @@ << "JavaScriptFeature does not appear to be configured."; return nullptr; } + } else { + world = JavaScriptFeatureManager::GetPageContentWorldForBrowserState( + web_state->GetBrowserState()); } WebFrameImpl* frame = static_cast(GetMainFrame(web_state));