1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// found in the LICENSE file.
4a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/browser/extensions/api/image_writer_private/error_messages.h"
6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/browser/extensions/api/image_writer_private/test_utils.h"
7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/browser/extensions/api/image_writer_private/write_from_url_operation.h"
8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/test/base/testing_profile.h"
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/public/browser/browser_thread.h"
101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/url_request/test_url_request_interceptor.h"
11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "net/url_request/url_fetcher.h"
12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace extensions {
14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace image_writer {
15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace {
17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciusing content::BrowserThread;
19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using testing::_;
20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using testing::AnyNumber;
21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using testing::AtLeast;
22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using testing::Gt;
23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using testing::Lt;
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const char kTestImageUrl[] = "http://localhost/test/image.zip";
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccitypedef net::LocalHostTestURLRequestInterceptor GetInterceptor;
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// This class gives us a generic Operation with the ability to set or inspect
30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// the current path to the image file.
31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class OperationForTest : public WriteFromUrlOperation {
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public:
33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  OperationForTest(base::WeakPtr<OperationManager> manager_,
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                   const ExtensionId& extension_id,
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                   net::URLRequestContextGetter* request_context,
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                   GURL url,
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                   const std::string& hash,
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                   const std::string& storage_unit_id)
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      : WriteFromUrlOperation(manager_,
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                              extension_id,
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                              request_context,
42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                              url,
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                              hash,
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                              storage_unit_id) {}
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void StartImpl() OVERRIDE {}
47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Expose stages for testing.
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void GetDownloadTarget(const base::Closure& continuation) {
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    WriteFromUrlOperation::GetDownloadTarget(continuation);
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void Download(const base::Closure& continuation) {
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    WriteFromUrlOperation::Download(continuation);
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void VerifyDownload(const base::Closure& continuation) {
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    WriteFromUrlOperation::VerifyDownload(continuation);
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Helpers to set-up state for intermediate stages.
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void SetImagePath(const base::FilePath image_path) {
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    image_path_ = image_path;
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::FilePath GetImagePath() { return image_path_; }
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) private:
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual ~OperationForTest() {};
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class ImageWriterWriteFromUrlOperationTest : public ImageWriterUnitTestBase {
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) protected:
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ImageWriterWriteFromUrlOperationTest() : manager_(&test_profile_) {}
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void SetUp() OVERRIDE {
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ImageWriterUnitTestBase::SetUp();
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Turn on interception and set up our dummy file.
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    net::URLFetcher::SetEnableInterceptionForTests(true);
811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    get_interceptor_.reset(new GetInterceptor(
821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO),
831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)));
85116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    get_interceptor_->SetResponse(GURL(kTestImageUrl),
86116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                  test_utils_.GetImagePath());
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void TearDown() OVERRIDE {
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ImageWriterUnitTestBase::TearDown();
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Remember to turn off global interception.
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    net::URLFetcher::SetEnableInterceptionForTests(false);
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_refptr<OperationForTest> CreateOperation(const GURL& url,
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                                  const std::string& hash) {
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    scoped_refptr<OperationForTest> operation(
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        new OperationForTest(manager_.AsWeakPtr(),
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             kDummyExtensionId,
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             test_profile_.GetRequestContext(),
102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             url,
103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                             hash,
104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                             test_utils_.GetDevicePath().AsUTF8Unsafe()));
105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    operation->Start();
106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return operation;
107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  TestingProfile test_profile_;
110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<GetInterceptor> get_interceptor_;
111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  MockOperationManager manager_;
113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(ImageWriterWriteFromUrlOperationTest, SelectTargetWithoutExtension) {
116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_refptr<OperationForTest> operation =
117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      CreateOperation(GURL("http://localhost/foo/bar"), "");
118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  operation->GetDownloadTarget(base::Bind(&base::DoNothing));
120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(FILE_PATH_LITERAL("bar"),
122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            operation->GetImagePath().BaseName().value());
123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  operation->Cancel();
125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(ImageWriterWriteFromUrlOperationTest, SelectTargetWithExtension) {
128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_refptr<OperationForTest> operation =
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      CreateOperation(GURL("http://localhost/foo/bar.zip"), "");
130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  operation->GetDownloadTarget(base::Bind(&base::DoNothing));
132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(FILE_PATH_LITERAL("bar.zip"),
134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            operation->GetImagePath().BaseName().value());
135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  operation->Cancel();
137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(ImageWriterWriteFromUrlOperationTest, DownloadFile) {
140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // This test actually triggers the URL fetch code, which will drain the
141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // message queues while waiting for IO, thus we have to run until the
142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // operation completes.
143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::RunLoop runloop;
144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::Closure quit_closure = runloop.QuitClosure();
145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::FilePath download_target_path;
146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_refptr<OperationForTest> operation =
147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      CreateOperation(GURL(kTestImageUrl), "");
148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_TRUE(base::CreateTemporaryFileInDir(test_utils_.GetTempDir(),
150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                             &download_target_path));
151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  operation->SetImagePath(download_target_path);
152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_CALL(
154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      manager_,
155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      OnProgress(kDummyExtensionId, image_writer_api::STAGE_DOWNLOAD, _))
156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      .Times(AtLeast(1));
157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_CALL(
158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      manager_,
159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      OnProgress(kDummyExtensionId, image_writer_api::STAGE_DOWNLOAD, 0))
160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      .Times(AnyNumber());
161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_CALL(
162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      manager_,
163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      OnProgress(kDummyExtensionId, image_writer_api::STAGE_DOWNLOAD, 100))
164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      .Times(AnyNumber());
165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
166a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  content::BrowserThread::PostTask(
167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      content::BrowserThread::FILE,
168a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      FROM_HERE,
169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::Bind(&OperationForTest::Download, operation, quit_closure));
170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  runloop.Run();
172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_TRUE(base::ContentsEqual(test_utils_.GetImagePath(),
174116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                  operation->GetImagePath()));
175a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(1, get_interceptor_->GetHitCount());
177a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
178a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  operation->Cancel();
179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(ImageWriterWriteFromUrlOperationTest, VerifyFile) {
182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<char[]> data_buffer(new char[kTestFileSize]);
183116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::ReadFile(test_utils_.GetImagePath(), data_buffer.get(), kTestFileSize);
184a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::MD5Digest expected_digest;
185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::MD5Sum(data_buffer.get(), kTestFileSize, &expected_digest);
186a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  std::string expected_hash = base::MD5DigestToBase16(expected_digest);
187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
188a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_refptr<OperationForTest> operation =
189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      CreateOperation(GURL(""), expected_hash);
190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_CALL(
192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      manager_,
193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      OnProgress(kDummyExtensionId, image_writer_api::STAGE_VERIFYDOWNLOAD, _))
194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      .Times(AtLeast(1));
195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_CALL(
196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      manager_,
197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      OnProgress(kDummyExtensionId, image_writer_api::STAGE_VERIFYDOWNLOAD, 0))
198a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      .Times(AtLeast(1));
199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_CALL(manager_,
200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)              OnProgress(kDummyExtensionId,
201a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         image_writer_api::STAGE_VERIFYDOWNLOAD,
202a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                         100)).Times(AtLeast(1));
203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
204116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  operation->SetImagePath(test_utils_.GetImagePath());
205a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  content::BrowserThread::PostTask(content::BrowserThread::FILE,
206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                   FROM_HERE,
207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                   base::Bind(&OperationForTest::VerifyDownload,
208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                              operation,
209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                              base::Bind(&base::DoNothing)));
210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::RunLoop().RunUntilIdle();
212a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
213a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  operation->Cancel();
214a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
215a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
216a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace
217a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace image_writer
219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace extensions
220