Commit 11fe369f authored by John Z Wu's avatar John Z Wu Committed by Commit Bot

Detect CSP errors from translate.js and pass it back to native code.

Currently all CSP errors are reported wrongly as INITIALIZATION_ERROR,
this change will report it as BAD_ORIGIN.

Change-Id: I2cc09d9dcd722ab0657605e540acac69e142eb6c
Bug: 686364
Reviewed-on: https://chromium-review.googlesource.com/1141047
Commit-Queue: John Wu <jzw@chromium.org>
Reviewed-by: default avatarDavid Roger <droger@chromium.org>
Reviewed-by: default avatarEugene But <eugenebut@chromium.org>
Cr-Commit-Position: refs/heads/master@{#585580}
parent f64b47d5
...@@ -114,6 +114,16 @@ cr.googleTranslate = (function() { ...@@ -114,6 +114,16 @@ cr.googleTranslate = (function() {
*/ */
var resultCallback; var resultCallback;
/**
* Listens to security policy violations to set |errorCode|.
*/
document.addEventListener('securitypolicyviolation', function(event) {
if (securityOrigin.startsWith(event.blockedURI)) {
errorCode = ERROR['BAD_ORIGIN'];
invokeReadyCallback();
}
});
function checkLibReady() { function checkLibReady() {
if (lib.isAvailable()) { if (lib.isAvailable()) {
readyTime = performance.now(); readyTime = performance.now();
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "components/language/ios/browser/ios_language_detection_tab_helper.h" #include "components/language/ios/browser/ios_language_detection_tab_helper.h"
#include "components/translate/core/browser/translate_driver.h" #include "components/translate/core/browser/translate_driver.h"
#include "components/translate/core/common/translate_errors.h"
#include "components/translate/ios/browser/language_detection_controller.h" #include "components/translate/ios/browser/language_detection_controller.h"
#include "components/translate/ios/browser/translate_controller.h" #include "components/translate/ios/browser/translate_controller.h"
#include "ios/web/public/web_state/web_state_observer.h" #include "ios/web/public/web_state/web_state_observer.h"
...@@ -86,10 +87,10 @@ class IOSTranslateDriver : public TranslateDriver, ...@@ -86,10 +87,10 @@ class IOSTranslateDriver : public TranslateDriver,
void OnLanguageDetermined(const LanguageDetectionDetails& details); void OnLanguageDetermined(const LanguageDetectionDetails& details);
// TranslateController::Observer methods. // TranslateController::Observer methods.
void OnTranslateScriptReady(bool success, void OnTranslateScriptReady(TranslateErrors::Type error_type,
double load_time, double load_time,
double ready_time) override; double ready_time) override;
void OnTranslateComplete(bool success, void OnTranslateComplete(TranslateErrors::Type error_type,
const std::string& original_language, const std::string& original_language,
double translation_time) override; double translation_time) override;
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
#include "components/translate/core/browser/translate_manager.h" #include "components/translate/core/browser/translate_manager.h"
#include "components/translate/core/common/language_detection_details.h" #include "components/translate/core/common/language_detection_details.h"
#include "components/translate/core/common/translate_constants.h" #include "components/translate/core/common/translate_constants.h"
#include "components/translate/core/common/translate_errors.h"
#include "components/translate/core/common/translate_metrics.h" #include "components/translate/core/common/translate_metrics.h"
#import "components/translate/ios/browser/js_language_detection_manager.h" #import "components/translate/ios/browser/js_language_detection_manager.h"
#import "components/translate/ios/browser/js_translate_manager.h" #import "components/translate/ios/browser/js_translate_manager.h"
...@@ -227,15 +226,16 @@ bool IOSTranslateDriver::IsPageValid(int page_seq_no) const { ...@@ -227,15 +226,16 @@ bool IOSTranslateDriver::IsPageValid(int page_seq_no) const {
// TranslateController::Observer implementation. // TranslateController::Observer implementation.
void IOSTranslateDriver::OnTranslateScriptReady(bool success, void IOSTranslateDriver::OnTranslateScriptReady(
double load_time, TranslateErrors::Type error_type,
double ready_time) { double load_time,
double ready_time) {
if (!IsPageValid(pending_page_seq_no_)) if (!IsPageValid(pending_page_seq_no_))
return; return;
if (!success) { if (error_type != TranslateErrors::NONE) {
translate_manager_->PageTranslated(source_language_, target_language_, translate_manager_->PageTranslated(source_language_, target_language_,
TranslateErrors::INITIALIZATION_ERROR); error_type);
return; return;
} }
...@@ -249,16 +249,15 @@ void IOSTranslateDriver::OnTranslateScriptReady(bool success, ...@@ -249,16 +249,15 @@ void IOSTranslateDriver::OnTranslateScriptReady(bool success,
} }
void IOSTranslateDriver::OnTranslateComplete( void IOSTranslateDriver::OnTranslateComplete(
bool success, TranslateErrors::Type error_type,
const std::string& original_language, const std::string& original_language,
double translation_time) { double translation_time) {
if (!IsPageValid(pending_page_seq_no_)) if (!IsPageValid(pending_page_seq_no_))
return; return;
if (!success) { if (error_type != TranslateErrors::NONE) {
// TODO(toyoshim): Check |errorCode| of translate.js and notify it here.
translate_manager_->PageTranslated(source_language_, target_language_, translate_manager_->PageTranslated(source_language_, target_language_,
TranslateErrors::TRANSLATION_ERROR); error_type);
} }
TranslationDidSucceed(source_language_, target_language_, TranslationDidSucceed(source_language_, target_language_,
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
cr.googleTranslate.readyCallback = function() { cr.googleTranslate.readyCallback = function() {
__gCrWeb.message.invokeOnHost({ __gCrWeb.message.invokeOnHost({
'command': 'translate.ready', 'command': 'translate.ready',
'timeout': cr.googleTranslate.error, 'errorCode': cr.googleTranslate.errorCode,
'loadTime': cr.googleTranslate.loadTime, 'loadTime': cr.googleTranslate.loadTime,
'readyTime': cr.googleTranslate.readyTime}); 'readyTime': cr.googleTranslate.readyTime});
} }
...@@ -27,7 +27,7 @@ cr.googleTranslate.readyCallback = function() { ...@@ -27,7 +27,7 @@ cr.googleTranslate.readyCallback = function() {
cr.googleTranslate.resultCallback = function() { cr.googleTranslate.resultCallback = function() {
__gCrWeb.message.invokeOnHost({ __gCrWeb.message.invokeOnHost({
'command': 'translate.status', 'command': 'translate.status',
'success': !cr.googleTranslate.error, 'errorCode': cr.googleTranslate.errorCode,
'originalPageLanguage': cr.googleTranslate.sourceLang, 'originalPageLanguage': cr.googleTranslate.sourceLang,
'translationTime': cr.googleTranslate.translationTime}); 'translationTime': cr.googleTranslate.translationTime});
} }
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "base/mac/scoped_nsobject.h" #include "base/mac/scoped_nsobject.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "components/translate/core/common/translate_errors.h"
#include "ios/web/public/web_state/web_state_observer.h" #include "ios/web/public/web_state/web_state_observer.h"
@class JsTranslateManager; @class JsTranslateManager;
...@@ -34,13 +35,14 @@ class TranslateController : public web::WebStateObserver { ...@@ -34,13 +35,14 @@ class TranslateController : public web::WebStateObserver {
class Observer { class Observer {
public: public:
// Called when the translate script is ready. // Called when the translate script is ready.
// In case of timeout, |success| is false. // |error_type| Indicates error code.
virtual void OnTranslateScriptReady(bool success, virtual void OnTranslateScriptReady(TranslateErrors::Type error_type,
double load_time, double load_time,
double ready_time) = 0; double ready_time) = 0;
// Called when the translation is complete. // Called when the translation is complete.
virtual void OnTranslateComplete(bool success, // |error_type| Indicates error code.
virtual void OnTranslateComplete(TranslateErrors::Type error_type,
const std::string& original_language, const std::string& original_language,
double translation_time) = 0; double translation_time) = 0;
}; };
......
...@@ -94,17 +94,21 @@ bool TranslateController::OnJavascriptCommandReceived( ...@@ -94,17 +94,21 @@ bool TranslateController::OnJavascriptCommandReceived(
bool TranslateController::OnTranslateReady( bool TranslateController::OnTranslateReady(
const base::DictionaryValue& command) { const base::DictionaryValue& command) {
if (!command.HasKey("timeout")) { double error_code = 0.;
double load_time = 0.;
double ready_time = 0.;
if (!command.HasKey("errorCode") ||
!command.GetDouble("errorCode", &error_code) ||
error_code < TranslateErrors::NONE ||
error_code >= TranslateErrors::TRANSLATE_ERROR_MAX) {
NOTREACHED(); NOTREACHED();
return false; return false;
} }
bool timeout = false; TranslateErrors::Type error_type =
double load_time = 0.; static_cast<TranslateErrors::Type>(error_code);
double ready_time = 0.; if (error_type == TranslateErrors::NONE) {
command.GetBoolean("timeout", &timeout);
if (!timeout) {
if (!command.HasKey("loadTime") || !command.HasKey("readyTime")) { if (!command.HasKey("loadTime") || !command.HasKey("readyTime")) {
NOTREACHED(); NOTREACHED();
return false; return false;
...@@ -113,23 +117,27 @@ bool TranslateController::OnTranslateReady( ...@@ -113,23 +117,27 @@ bool TranslateController::OnTranslateReady(
command.GetDouble("readyTime", &ready_time); command.GetDouble("readyTime", &ready_time);
} }
if (observer_) if (observer_)
observer_->OnTranslateScriptReady(!timeout, load_time, ready_time); observer_->OnTranslateScriptReady(error_type, load_time, ready_time);
return true; return true;
} }
bool TranslateController::OnTranslateComplete( bool TranslateController::OnTranslateComplete(
const base::DictionaryValue& command) { const base::DictionaryValue& command) {
if (!command.HasKey("success")) { double error_code = 0.;
std::string original_language;
double translation_time = 0.;
if (!command.HasKey("errorCode") ||
!command.GetDouble("errorCode", &error_code) ||
error_code < TranslateErrors::NONE ||
error_code >= TranslateErrors::TRANSLATE_ERROR_MAX) {
NOTREACHED(); NOTREACHED();
return false; return false;
} }
bool success = false; TranslateErrors::Type error_type =
std::string original_language; static_cast<TranslateErrors::Type>(error_code);
double translation_time = 0.; if (error_type == TranslateErrors::NONE) {
command.GetBoolean("success", &success);
if (success) {
if (!command.HasKey("originalPageLanguage") || if (!command.HasKey("originalPageLanguage") ||
!command.HasKey("translationTime")) { !command.HasKey("translationTime")) {
NOTREACHED(); NOTREACHED();
...@@ -140,7 +148,7 @@ bool TranslateController::OnTranslateComplete( ...@@ -140,7 +148,7 @@ bool TranslateController::OnTranslateComplete(
} }
if (observer_) if (observer_)
observer_->OnTranslateComplete(success, original_language, observer_->OnTranslateComplete(error_type, original_language,
translation_time); translation_time);
return true; return true;
} }
......
...@@ -24,7 +24,7 @@ class TranslateControllerTest : public PlatformTest, ...@@ -24,7 +24,7 @@ class TranslateControllerTest : public PlatformTest,
protected: protected:
TranslateControllerTest() TranslateControllerTest()
: test_web_state_(new web::TestWebState), : test_web_state_(new web::TestWebState),
success_(false), error_type_(TranslateErrors::Type::NONE),
ready_time_(0), ready_time_(0),
load_time_(0), load_time_(0),
translation_time_(0), translation_time_(0),
...@@ -38,20 +38,20 @@ class TranslateControllerTest : public PlatformTest, ...@@ -38,20 +38,20 @@ class TranslateControllerTest : public PlatformTest,
} }
// TranslateController::Observer methods. // TranslateController::Observer methods.
void OnTranslateScriptReady(bool success, void OnTranslateScriptReady(TranslateErrors::Type error_type,
double load_time, double load_time,
double ready_time) override { double ready_time) override {
on_script_ready_called_ = true; on_script_ready_called_ = true;
success_ = success; error_type_ = error_type;
load_time_ = load_time; load_time_ = load_time;
ready_time_ = ready_time; ready_time_ = ready_time;
} }
void OnTranslateComplete(bool success, void OnTranslateComplete(TranslateErrors::Type error_type,
const std::string& original_language, const std::string& original_language,
double translation_time) override { double translation_time) override {
on_translate_complete_called_ = true; on_translate_complete_called_ = true;
success_ = success; error_type_ = error_type;
original_language_ = original_language; original_language_ = original_language;
translation_time_ = translation_time; translation_time_ = translation_time;
} }
...@@ -59,7 +59,7 @@ class TranslateControllerTest : public PlatformTest, ...@@ -59,7 +59,7 @@ class TranslateControllerTest : public PlatformTest,
std::unique_ptr<web::TestWebState> test_web_state_; std::unique_ptr<web::TestWebState> test_web_state_;
id mock_js_translate_manager_; id mock_js_translate_manager_;
std::unique_ptr<TranslateController> translate_controller_; std::unique_ptr<TranslateController> translate_controller_;
bool success_; TranslateErrors::Type error_type_;
double ready_time_; double ready_time_;
double load_time_; double load_time_;
std::string original_language_; std::string original_language_;
...@@ -80,7 +80,7 @@ TEST_F(TranslateControllerTest, OnJavascriptCommandReceived) { ...@@ -80,7 +80,7 @@ TEST_F(TranslateControllerTest, OnJavascriptCommandReceived) {
TEST_F(TranslateControllerTest, OnIFrameJavascriptCommandReceived) { TEST_F(TranslateControllerTest, OnIFrameJavascriptCommandReceived) {
base::DictionaryValue command; base::DictionaryValue command;
command.SetString("command", "translate.ready"); command.SetString("command", "translate.ready");
command.SetBoolean("timeout", true); command.SetDouble("errorCode", TranslateErrors::TRANSLATION_TIMEOUT);
command.SetDouble("loadTime", .0); command.SetDouble("loadTime", .0);
command.SetDouble("readyTime", .0); command.SetDouble("readyTime", .0);
EXPECT_FALSE(translate_controller_->OnJavascriptCommandReceived( EXPECT_FALSE(translate_controller_->OnJavascriptCommandReceived(
...@@ -93,7 +93,7 @@ TEST_F(TranslateControllerTest, OnIFrameJavascriptCommandReceived) { ...@@ -93,7 +93,7 @@ TEST_F(TranslateControllerTest, OnIFrameJavascriptCommandReceived) {
TEST_F(TranslateControllerTest, OnTranslateScriptReadyTimeoutCalled) { TEST_F(TranslateControllerTest, OnTranslateScriptReadyTimeoutCalled) {
base::DictionaryValue command; base::DictionaryValue command;
command.SetString("command", "translate.ready"); command.SetString("command", "translate.ready");
command.SetBoolean("timeout", true); command.SetDouble("errorCode", TranslateErrors::TRANSLATION_TIMEOUT);
command.SetDouble("loadTime", .0); command.SetDouble("loadTime", .0);
command.SetDouble("readyTime", .0); command.SetDouble("readyTime", .0);
EXPECT_TRUE(translate_controller_->OnJavascriptCommandReceived( EXPECT_TRUE(translate_controller_->OnJavascriptCommandReceived(
...@@ -101,11 +101,11 @@ TEST_F(TranslateControllerTest, OnTranslateScriptReadyTimeoutCalled) { ...@@ -101,11 +101,11 @@ TEST_F(TranslateControllerTest, OnTranslateScriptReadyTimeoutCalled) {
/*is_main_frame=*/true)); /*is_main_frame=*/true));
EXPECT_TRUE(on_script_ready_called_); EXPECT_TRUE(on_script_ready_called_);
EXPECT_FALSE(on_translate_complete_called_); EXPECT_FALSE(on_translate_complete_called_);
EXPECT_FALSE(success_); EXPECT_FALSE(error_type_ == TranslateErrors::NONE);
} }
// Tests that OnTranslateScriptReady() is called with the right parameters when // Tests that OnTranslateScriptReady() is called with the right parameters when
// a |translate.ready| message is recieved from the JS side. // a |translate.ready| message is received from the JS side.
TEST_F(TranslateControllerTest, OnTranslateScriptReadyCalled) { TEST_F(TranslateControllerTest, OnTranslateScriptReadyCalled) {
// Arbitrary values. // Arbitrary values.
double some_load_time = 23.1; double some_load_time = 23.1;
...@@ -113,7 +113,7 @@ TEST_F(TranslateControllerTest, OnTranslateScriptReadyCalled) { ...@@ -113,7 +113,7 @@ TEST_F(TranslateControllerTest, OnTranslateScriptReadyCalled) {
base::DictionaryValue command; base::DictionaryValue command;
command.SetString("command", "translate.ready"); command.SetString("command", "translate.ready");
command.SetBoolean("timeout", false); command.SetDouble("errorCode", TranslateErrors::NONE);
command.SetDouble("loadTime", some_load_time); command.SetDouble("loadTime", some_load_time);
command.SetDouble("readyTime", some_ready_time); command.SetDouble("readyTime", some_ready_time);
EXPECT_TRUE(translate_controller_->OnJavascriptCommandReceived( EXPECT_TRUE(translate_controller_->OnJavascriptCommandReceived(
...@@ -121,13 +121,13 @@ TEST_F(TranslateControllerTest, OnTranslateScriptReadyCalled) { ...@@ -121,13 +121,13 @@ TEST_F(TranslateControllerTest, OnTranslateScriptReadyCalled) {
/*is_main_frame=*/true)); /*is_main_frame=*/true));
EXPECT_TRUE(on_script_ready_called_); EXPECT_TRUE(on_script_ready_called_);
EXPECT_FALSE(on_translate_complete_called_); EXPECT_FALSE(on_translate_complete_called_);
EXPECT_TRUE(success_); EXPECT_TRUE(error_type_ == TranslateErrors::NONE);
EXPECT_EQ(some_load_time, load_time_); EXPECT_EQ(some_load_time, load_time_);
EXPECT_EQ(some_ready_time, ready_time_); EXPECT_EQ(some_ready_time, ready_time_);
} }
// Tests that OnTranslateComplete() is called with the right parameters when a // Tests that OnTranslateComplete() is called with the right parameters when a
// |translate.status| message is recieved from the JS side. // |translate.status| message is received from the JS side.
TEST_F(TranslateControllerTest, TranslationSuccess) { TEST_F(TranslateControllerTest, TranslationSuccess) {
// Arbitrary values. // Arbitrary values.
std::string some_original_language("en"); std::string some_original_language("en");
...@@ -135,7 +135,7 @@ TEST_F(TranslateControllerTest, TranslationSuccess) { ...@@ -135,7 +135,7 @@ TEST_F(TranslateControllerTest, TranslationSuccess) {
base::DictionaryValue command; base::DictionaryValue command;
command.SetString("command", "translate.status"); command.SetString("command", "translate.status");
command.SetBoolean("success", true); command.SetDouble("errorCode", TranslateErrors::NONE);
command.SetString("originalPageLanguage", some_original_language); command.SetString("originalPageLanguage", some_original_language);
command.SetDouble("translationTime", some_translation_time); command.SetDouble("translationTime", some_translation_time);
EXPECT_TRUE(translate_controller_->OnJavascriptCommandReceived( EXPECT_TRUE(translate_controller_->OnJavascriptCommandReceived(
...@@ -143,23 +143,23 @@ TEST_F(TranslateControllerTest, TranslationSuccess) { ...@@ -143,23 +143,23 @@ TEST_F(TranslateControllerTest, TranslationSuccess) {
/*is_main_frame=*/true)); /*is_main_frame=*/true));
EXPECT_FALSE(on_script_ready_called_); EXPECT_FALSE(on_script_ready_called_);
EXPECT_TRUE(on_translate_complete_called_); EXPECT_TRUE(on_translate_complete_called_);
EXPECT_TRUE(success_); EXPECT_TRUE(error_type_ == TranslateErrors::NONE);
EXPECT_EQ(some_original_language, original_language_); EXPECT_EQ(some_original_language, original_language_);
EXPECT_EQ(some_translation_time, translation_time_); EXPECT_EQ(some_translation_time, translation_time_);
} }
// Tests that OnTranslateComplete() is called with the right parameters when a // Tests that OnTranslateComplete() is called with the right parameters when a
// |translate.status| message is recieved from the JS side. // |translate.status| message is received from the JS side.
TEST_F(TranslateControllerTest, TranslationFailure) { TEST_F(TranslateControllerTest, TranslationFailure) {
base::DictionaryValue command; base::DictionaryValue command;
command.SetString("command", "translate.status"); command.SetString("command", "translate.status");
command.SetBoolean("success", false); command.SetDouble("errorCode", TranslateErrors::INITIALIZATION_ERROR);
EXPECT_TRUE(translate_controller_->OnJavascriptCommandReceived( EXPECT_TRUE(translate_controller_->OnJavascriptCommandReceived(
command, GURL("http://google.com"), /*interacting*/ false, command, GURL("http://google.com"), /*interacting*/ false,
/*is_main_frame=*/true)); /*is_main_frame=*/true));
EXPECT_FALSE(on_script_ready_called_); EXPECT_FALSE(on_script_ready_called_);
EXPECT_TRUE(on_translate_complete_called_); EXPECT_TRUE(on_translate_complete_called_);
EXPECT_FALSE(success_); EXPECT_FALSE(error_type_ == TranslateErrors::NONE);
} }
} // namespace translate } // 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