Commit 8eb0e149 authored by John Z Wu's avatar John Z Wu Committed by Commit Bot

Test invalid "translate.sendrequest" js commands

- Test URLs that do not match the security origin are not handled.
- Test invalid HTTP methods cause the request to fail.

Bug: 1110195
Change-Id: I13ab6c290c752a459e57ba4446dd133bd6d844e8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2368146Reviewed-by: default avatarDavid Roger <droger@chromium.org>
Commit-Queue: John Wu <jzw@chromium.org>
Cr-Commit-Position: refs/heads/master@{#801100}
parent 496972ab
......@@ -33,6 +33,21 @@
// has been translated.
- (void)revertTranslation;
// Returns the response to a XHR request that was proxied to the browser from
// javascript. See function __gCrWeb.translate.handleResponse.
// |URL| The original URL that was requested.
// |requestID| An ID for keeping track of inflight requests.
// |responeCode| The HTTP response code.
// |statusText| The status text associated with the response code, may be empty.
// |responseURL| The final URL from which the response originates.
// |responseText| The contents of the response.
- (void)handleTranslateResponseWithURL:(NSString*)URL
requestID:(int)requestID
responseCode:(int)responseCode
statusText:(NSString*)statusText
responseURL:(NSString*)responseURL
responseText:(NSString*)responseText;
@end
#endif // COMPONENTS_TRANSLATE_IOS_BROWSER_JS_TRANSLATE_MANAGER_H_
......@@ -56,6 +56,22 @@
completionHandler:nil];
}
- (void)handleTranslateResponseWithURL:(NSString*)URL
requestID:(int)requestID
responseCode:(int)responseCode
statusText:(NSString*)statusText
responseURL:(NSString*)responseURL
responseText:(NSString*)responseText {
DCHECK([self hasBeenInjected]);
// Return the response details to function defined in translate_ios.js.
NSString* script = [NSString
stringWithFormat:
@"__gCrWeb.translate.handleResponse('%@', %d, %d, '%@', '%@', '%@')",
URL, requestID, responseCode, statusText, responseURL, responseText];
[self.receiver executeJavaScript:script completionHandler:nil];
}
#pragma mark -
#pragma mark CRWJSInjectionManager methods
......
......@@ -84,7 +84,12 @@ class TranslateController : public web::WebStateObserver {
FRIEND_TEST_ALL_PREFIXES(TranslateControllerTest, TranslationSuccess);
FRIEND_TEST_ALL_PREFIXES(TranslateControllerTest, TranslationFailure);
FRIEND_TEST_ALL_PREFIXES(TranslateControllerTest, OnTranslateLoadJavascript);
FRIEND_TEST_ALL_PREFIXES(TranslateControllerTest, OnTranslateSendRequest);
FRIEND_TEST_ALL_PREFIXES(TranslateControllerTest,
OnTranslateSendRequestWithValidCommand);
FRIEND_TEST_ALL_PREFIXES(TranslateControllerTest,
OnTranslateSendRequestWithBadURL);
FRIEND_TEST_ALL_PREFIXES(TranslateControllerTest,
OnTranslateSendRequestWithBadMethod);
// Called when a JavaScript command is received.
bool OnJavascriptCommandReceived(const base::DictionaryValue& command,
......
......@@ -22,6 +22,7 @@
#include "ios/web/public/navigation/navigation_context.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/http/http_status_code.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
......@@ -255,15 +256,20 @@ void TranslateController::OnRequestFetchComplete(
std::unique_ptr<std::string> response_body) {
const std::unique_ptr<network::SimpleURLLoader>& url_loader = *it;
// |ResponseInfo()| may be a nullptr if response is incomplete.
int response_code = 0;
std::string status_text;
const network::mojom::URLResponseHead* response_head =
url_loader->ResponseInfo();
if (response_head && response_head->headers) {
int net_error_code = url_loader->NetError();
// |ResponseInfo()| may be a nullptr if response is incomplete.
if (net_error_code == net::Error::OK && response_head &&
response_head->headers) {
net::HttpResponseHeaders* headers = response_head->headers.get();
response_code = headers->response_code();
status_text = headers->GetStatusText();
} else {
response_code = net::HttpStatusCode::HTTP_BAD_REQUEST;
}
// Escape the returned string so it can be parsed by JSON.parse.
......@@ -272,12 +278,15 @@ void TranslateController::OnRequestFetchComplete(
base::EscapeJSONString(response_text, /*put_in_quotes=*/false,
&escaped_response_text);
// Return the response details to function defined in translate_ios.js.
std::string script = base::StringPrintf(
"__gCrWeb.translate.handleResponse('%s', %d, %d, '%s', '%s', '%s')",
url.c_str(), request_id, response_code, status_text.c_str(),
url_loader->GetFinalURL().spec().c_str(), escaped_response_text.c_str());
web_state_->ExecuteJavaScript(base::UTF8ToUTF16(script));
std::string final_url = url_loader->GetFinalURL().spec();
[js_manager_
handleTranslateResponseWithURL:base::SysUTF8ToNSString(url)
requestID:request_id
responseCode:response_code
statusText:base::SysUTF8ToNSString(status_text)
responseURL:base::SysUTF8ToNSString(final_url)
responseText:base::SysUTF8ToNSString(
escaped_response_text)];
request_fetchers_.erase(it);
}
......
......@@ -12,6 +12,7 @@
#include "ios/web/public/test/fakes/test_browser_state.h"
#import "ios/web/public/test/fakes/test_web_state.h"
#include "ios/web/public/test/web_task_environment.h"
#include "net/http/http_status_code.h"
#include "testing/platform_test.h"
#import "third_party/ocmock/OCMock/OCMock.h"
#include "url/gurl.h"
......@@ -173,7 +174,7 @@ TEST_F(TranslateControllerTest, TranslationFailure) {
EXPECT_FALSE(error_type_ == TranslateErrors::NONE);
}
// Tests that OnTranslateLoadJavaScript() is called with the right paramters
// Tests that OnTranslateLoadJavaScript() is called with the right parameters
// when a |translate.loadjavascript| message is received from the JS side.
TEST_F(TranslateControllerTest, OnTranslateLoadJavascript) {
base::DictionaryValue command;
......@@ -184,9 +185,9 @@ TEST_F(TranslateControllerTest, OnTranslateLoadJavascript) {
&fake_main_frame_));
}
// Tests that OnTranslateSendRequest() is called with the right paramters
// Tests that OnTranslateSendRequest() is called with the right parameters
// when a |translate.sendrequest| message is received from the JS side.
TEST_F(TranslateControllerTest, OnTranslateSendRequest) {
TEST_F(TranslateControllerTest, OnTranslateSendRequestWithValidCommand) {
base::DictionaryValue command;
command.SetString("command", "translate.sendrequest");
command.SetString("method", "POST");
......@@ -199,4 +200,49 @@ TEST_F(TranslateControllerTest, OnTranslateSendRequest) {
&fake_main_frame_));
}
// Tests that OnTranslateSendRequest() rejects a bad url contained in the
// |translate.sendrequest| message received from Javascript.
TEST_F(TranslateControllerTest, OnTranslateSendRequestWithBadURL) {
base::DictionaryValue command;
command.SetString("command", "translate.sendrequest");
command.SetString("method", "POST");
command.SetString("url", "https://badurl.example.com");
command.SetString("body", "helloworld");
command.SetDouble("requestID", 0);
EXPECT_FALSE(translate_controller_->OnJavascriptCommandReceived(
command, GURL("http://google.com"), /*interacting=*/false,
&fake_main_frame_));
}
// Tests that OnTranslateSendRequest() called with a bad method will eventually
// cause the request to fail.
TEST_F(TranslateControllerTest, OnTranslateSendRequestWithBadMethod) {
base::DictionaryValue command;
command.SetString("command", "translate.sendrequest");
command.SetString("method", "POST\r\nHost: other.example.com");
command.SetString("url",
"https://translate.googleapis.com/translate?key=abcd");
command.SetString("body", "helloworld");
command.SetDouble("requestID", 0);
[[mock_js_translate_manager_ expect]
handleTranslateResponseWithURL:
@"https://translate.googleapis.com/translate?key=abcd"
requestID:0
responseCode:net::HttpStatusCode::HTTP_BAD_REQUEST
statusText:@""
responseURL:@"https://translate.googleapis.com/"
@"translate?key=abcd"
responseText:@""];
// The command will be accepted, but a bad method should cause the request to
// fail shortly thereafter.
EXPECT_TRUE(translate_controller_->OnJavascriptCommandReceived(
command, GURL("http://google.com"), /*interacting=*/false,
&fake_main_frame_));
task_environment_.RunUntilIdle();
[mock_js_translate_manager_ verify];
}
} // namespace translate
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment