blob: 4ad6cf1a2a2eac5660695a0f490663296d0c25c1 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/chrome/browser/web/image_fetch_tab_helper.h"
#include "base/strings/sys_string_conversions.h"
#import "base/test/ios/wait_util.h"
#include "base/test/metrics/histogram_tester.h"
#import "ios/web/public/test/web_test_with_web_state.h"
#include "net/http/http_util.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/gtest_mac.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
using base::test::ios::WaitUntilConditionOrTimeout;
namespace {
// Timeout for calling on ImageFetchTabHelper::GetImageData.
const NSTimeInterval kWaitForGetImageDataTimeout = 1.0;
const char kImageUrl[] = "http://www.chrooooooooooome.com/";
const char kImageData[] = "abc";
}
// Test fixture for ImageFetchTabHelper class.
class ImageFetchTabHelperTest : public web::WebTestWithWebState {
protected:
ImageFetchTabHelperTest()
: web::WebTestWithWebState(
web::TestWebThreadBundle::Options::IO_MAINLOOP) {}
void SetUp() override {
WebTestWithWebState::SetUp();
ASSERT_TRUE(LoadHtml("<html></html>"));
ImageFetchTabHelper::CreateForWebState(web_state());
SetUpTestSharedURLLoaderFactory();
}
// Sets up the network::TestURLLoaderFactory to handle download request.
void SetUpTestSharedURLLoaderFactory() {
SetSharedURLLoaderFactory(
base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
&test_url_loader_factory_));
network::ResourceResponseHead head;
std::string raw_header =
"HTTP/1.1 200 OK\n"
"Content-type: image/png\n\n";
head.headers = base::MakeRefCounted<net::HttpResponseHeaders>(
net::HttpUtil::AssembleRawHeaders(raw_header.c_str(),
raw_header.size()));
head.mime_type = "image/png";
network::URLLoaderCompletionStatus status;
status.decoded_body_length = strlen(kImageData);
test_url_loader_factory_.AddResponse(GURL(kImageUrl), head, kImageData,
status);
}
ImageFetchTabHelper* image_fetch_tab_helper() {
return ImageFetchTabHelper::FromWebState(web_state());
}
// Returns the expected image data in NSData*.
NSData* GetExpectedData() const {
return [base::SysUTF8ToNSString(kImageData)
dataUsingEncoding:NSUTF8StringEncoding];
}
network::TestURLLoaderFactory test_url_loader_factory_;
base::HistogramTester histogram_tester_;
DISALLOW_COPY_AND_ASSIGN(ImageFetchTabHelperTest);
};
// Tests that ImageFetchTabHelper::GetImageData can get image data from Js.
TEST_F(ImageFetchTabHelperTest, GetImageDataWithJsSucceedFromCanvas) {
// Inject fake |__gCrWeb.imageFetch.getImageData| that returns |kImageData|
// in base64 format.
id script_result = ExecuteJavaScript([NSString
stringWithFormat:
@"__gCrWeb.imageFetch = {}; __gCrWeb.imageFetch.getImageData = "
"function(id, url) { __gCrWeb.message.invokeOnHost({'command': "
"'imageFetch.getImageData', 'id': id, 'data': btoa('%s'), "
"'from':'canvas'}); }; true;",
kImageData]);
ASSERT_NSEQ(@YES, script_result);
__block bool callback_invoked = false;
image_fetch_tab_helper()->GetImageData(GURL(kImageUrl), web::Referrer(),
^(NSData* data) {
ASSERT_TRUE(data);
EXPECT_NSEQ(GetExpectedData(), data);
callback_invoked = true;
});
EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForGetImageDataTimeout, ^{
base::RunLoop().RunUntilIdle();
return callback_invoked;
}));
histogram_tester_.ExpectUniqueSample(
kUmaGetImageDataByJsResult,
ContextMenuGetImageDataByJsResult::kCanvasSucceed, 1);
}
// Tests that ImageFetchTabHelper::GetImageData can get image data from Js.
TEST_F(ImageFetchTabHelperTest, GetImageDataWithJsSucceedFromXmlHttpRequest) {
// Inject fake |__gCrWeb.imageFetch.getImageData| that returns |kImageData|
// in base64 format.
id script_result = ExecuteJavaScript([NSString
stringWithFormat:
@"__gCrWeb.imageFetch = {}; __gCrWeb.imageFetch.getImageData = "
"function(id, url) { __gCrWeb.message.invokeOnHost({'command': "
"'imageFetch.getImageData', 'id': id, 'data': btoa('%s'), "
"'from':'xhr'}); }; true;",
kImageData]);
ASSERT_NSEQ(@YES, script_result);
__block bool callback_invoked = false;
image_fetch_tab_helper()->GetImageData(GURL(kImageUrl), web::Referrer(),
^(NSData* data) {
ASSERT_TRUE(data);
EXPECT_NSEQ(GetExpectedData(), data);
callback_invoked = true;
});
EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForGetImageDataTimeout, ^{
base::RunLoop().RunUntilIdle();
return callback_invoked;
}));
histogram_tester_.ExpectUniqueSample(
kUmaGetImageDataByJsResult,
ContextMenuGetImageDataByJsResult::kXMLHttpRequestSucceed, 1);
}
// Tests that ImageFetchTabHelper::GetImageData gets image data from server when
// Js fails.
TEST_F(ImageFetchTabHelperTest, GetImageDataWithJsFail) {
id script_result = ExecuteJavaScript(
@"__gCrWeb.imageFetch = {}; __gCrWeb.imageFetch.getImageData = "
"function(id, url) { __gCrWeb.message.invokeOnHost({'command': "
"'imageFetch.getImageData', 'id': id}); }; true;");
ASSERT_NSEQ(@YES, script_result);
__block bool callback_invoked = false;
image_fetch_tab_helper()->GetImageData(GURL(kImageUrl), web::Referrer(),
^(NSData* data) {
ASSERT_TRUE(data);
EXPECT_NSEQ(GetExpectedData(), data);
callback_invoked = true;
});
EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForGetImageDataTimeout, ^{
base::RunLoop().RunUntilIdle();
return callback_invoked;
}));
histogram_tester_.ExpectUniqueSample(
kUmaGetImageDataByJsResult, ContextMenuGetImageDataByJsResult::kFail, 1);
}
// Tests that ImageFetchTabHelper::GetImageData gets image data from server when
// Js does not send a message back.
TEST_F(ImageFetchTabHelperTest, GetImageDataWithJsTimeout) {
// Inject fake |__gCrWeb.imageFetch.getImageData| that does not do anything.
id script_result = ExecuteJavaScript(
@"__gCrWeb.imageFetch = {}; __gCrWeb.imageFetch.getImageData = "
@"function(id, url) {}; true;");
ASSERT_NSEQ(@YES, script_result);
__block bool callback_invoked = false;
image_fetch_tab_helper()->GetImageData(GURL(kImageUrl), web::Referrer(),
^(NSData* data) {
ASSERT_TRUE(data);
EXPECT_NSEQ(GetExpectedData(), data);
callback_invoked = true;
});
EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForGetImageDataTimeout, ^{
base::RunLoop().RunUntilIdle();
return callback_invoked;
}));
histogram_tester_.ExpectUniqueSample(
kUmaGetImageDataByJsResult, ContextMenuGetImageDataByJsResult::kTimeout,
1);
}
// Tests that ImageFetchTabHelper::GetImageData gets image data from server when
// WebState is destroyed.
TEST_F(ImageFetchTabHelperTest, GetImageDataWithWebStateDestroy) {
// Inject fake |__gCrWeb.imageFetch.getImageData| that does not do anything.
id script_result = ExecuteJavaScript(
@"__gCrWeb.imageFetch = {}; __gCrWeb.imageFetch.getImageData = "
@"function(id, url) {}; true;");
ASSERT_NSEQ(@YES, script_result);
__block bool callback_invoked = false;
image_fetch_tab_helper()->GetImageData(GURL(kImageUrl), web::Referrer(),
^(NSData* data) {
ASSERT_TRUE(data);
EXPECT_NSEQ(GetExpectedData(), data);
callback_invoked = true;
});
DestroyWebState();
EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForGetImageDataTimeout, ^{
base::RunLoop().RunUntilIdle();
return callback_invoked;
}));
histogram_tester_.ExpectTotalCount(kUmaGetImageDataByJsResult, 0);
}
// Tests that ImageFetchTabHelper::GetImageData gets image data from server when
// WebState navigates to a new web page.
TEST_F(ImageFetchTabHelperTest, GetImageDataWithWebStateNavigate) {
// Inject fake |__gCrWeb.imageFetch.getImageData| that does not do anything.
id script_result = ExecuteJavaScript(
@"__gCrWeb.imageFetch = {}; __gCrWeb.imageFetch.getImageData = "
@"function(id, url) {}; true;");
ASSERT_NSEQ(@YES, script_result);
__block bool callback_invoked = false;
image_fetch_tab_helper()->GetImageData(GURL(kImageUrl), web::Referrer(),
^(NSData* data) {
ASSERT_TRUE(data);
EXPECT_NSEQ(GetExpectedData(), data);
callback_invoked = true;
});
LoadHtml(@"<html>new</html>"), GURL("http://new.webpage.com/");
EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForGetImageDataTimeout, ^{
base::RunLoop().RunUntilIdle();
return callback_invoked;
}));
histogram_tester_.ExpectTotalCount(kUmaGetImageDataByJsResult, 0);
}