content_verifier_browsertest.cc revision 010d83a9304c5a91596085d917d248abff47903a
145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org// Copyright 2014 The Chromium Authors. All rights reserved. 245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org// Use of this source code is governed by a BSD-style license that can be 345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org// found in the LICENSE file. 445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "base/scoped_observer.h" 645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "chrome/browser/extensions/extension_browsertest.h" 745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "content/public/test/test_utils.h" 845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "extensions/browser/content_verify_job.h" 945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "extensions/browser/extension_prefs.h" 1045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "extensions/browser/extension_registry.h" 1145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "extensions/browser/extension_registry_observer.h" 1245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "extensions/common/switches.h" 1345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 1445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgnamespace extensions { 1545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 1645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgnamespace { 1745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 1845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org// Helper for observing extension unloads. 1945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass UnloadObserver : public ExtensionRegistryObserver { 2045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org public: 2145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org explicit UnloadObserver(ExtensionRegistry* registry) : observer_(this) { 2245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org observer_.Add(registry); 2345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 2445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org virtual ~UnloadObserver() {} 2545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 2645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org void WaitForUnload(const ExtensionId& id) { 2745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (ContainsKey(observed_, id)) 2845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return; 2945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 3045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ASSERT_TRUE(loop_runner_.get() == NULL); 3145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org awaited_id_ = id; 3245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org loop_runner_ = new content::MessageLoopRunner(); 3345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org loop_runner_->Run(); 3445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 3545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 3645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org virtual void OnExtensionUnloaded( 3745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org content::BrowserContext* browser_context, 3845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org const Extension* extension, 3945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org UnloadedExtensionInfo::Reason reason) OVERRIDE { 4045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org observed_.insert(extension->id()); 4145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (awaited_id_ == extension->id()) 4245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org loop_runner_->Quit(); 4345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 4445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 4545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org private: 4645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ExtensionId awaited_id_; 4745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org std::set<ExtensionId> observed_; 4845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org scoped_refptr<content::MessageLoopRunner> loop_runner_; 4945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ScopedObserver<ExtensionRegistry, UnloadObserver> observer_; 5045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}; 5145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 5245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org// Helper for forcing ContentVerifyJob's to return an error. 5345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass JobDelegate : public ContentVerifyJob::TestDelegate { 5445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org public: 5545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org JobDelegate() : fail_next_read_(false), fail_next_done_(false) {} 5645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 5745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org virtual ~JobDelegate() {} 5845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 5945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org void set_id(const ExtensionId& id) { id_ = id; } 6045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org void fail_next_read() { fail_next_read_ = true; } 6145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org void fail_next_done() { fail_next_done_ = true; } 6245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 6345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org virtual ContentVerifyJob::FailureReason BytesRead(const ExtensionId& id, 6445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int count, 6545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org const char* data) OVERRIDE { 6645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (id == id_ && fail_next_read_) { 6745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fail_next_read_ = false; 6845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return ContentVerifyJob::HASH_MISMATCH; 6945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 7045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return ContentVerifyJob::NONE; 7145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 7245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 7345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org virtual ContentVerifyJob::FailureReason DoneReading( 7445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org const ExtensionId& id) OVERRIDE { 7545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (id == id_ && fail_next_done_) { 7645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org fail_next_done_ = false; 7745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return ContentVerifyJob::HASH_MISMATCH; 7845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 7945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return ContentVerifyJob::NONE; 8045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 8145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 8245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org private: 8345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org DISALLOW_COPY_AND_ASSIGN(JobDelegate); 8445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 8545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ExtensionId id_; 8645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bool fail_next_read_; 8745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org bool fail_next_done_; 8845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}; 8945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 9045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} // namespace 9145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 9245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgclass ContentVerifierTest : public ExtensionBrowserTest { 9345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org public: 9445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ContentVerifierTest() {} 9545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org virtual ~ContentVerifierTest() {} 9645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 9745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org virtual void SetUpCommandLine(base::CommandLine* command_line) OVERRIDE { 9845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ExtensionBrowserTest::SetUpCommandLine(command_line); 9945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org command_line->AppendSwitchASCII( 10045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org switches::kExtensionContentVerification, 10145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org switches::kExtensionContentVerificationEnforce); 10245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 10345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 10445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org // Setup our unload observer and JobDelegate, and install a test extension. 10545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org virtual void SetUpOnMainThread() OVERRIDE { 10645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ExtensionBrowserTest::SetUpOnMainThread(); 10745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unload_observer_.reset( 10845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org new UnloadObserver(ExtensionRegistry::Get(profile()))); 10945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org const Extension* extension = InstallExtensionFromWebstore( 11045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org test_data_dir_.AppendASCII("content_verifier/v1.crx"), 1); 11145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ASSERT_TRUE(extension); 11245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org id_ = extension->id(); 11345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org page_url_ = extension->GetResourceURL("page.html"); 11445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org delegate_.set_id(id_); 11545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ContentVerifyJob::SetDelegateForTests(&delegate_); 11645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 11745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 11845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org virtual void TearDownOnMainThread() OVERRIDE { 11945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ContentVerifyJob::SetDelegateForTests(NULL); 12045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ExtensionBrowserTest::TearDownOnMainThread(); 12145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 12245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 12345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org virtual void OpenPageAndWaitForUnload() { 12445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org AddTabAtIndex(1, page_url_, content::PAGE_TRANSITION_LINK); 12545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unload_observer_->WaitForUnload(id_); 12645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ExtensionPrefs* prefs = ExtensionPrefs::Get(profile()); 12745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org int reasons = prefs->GetDisableReasons(id_); 12845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org EXPECT_TRUE(reasons & Extension::DISABLE_CORRUPTED); 12945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 13045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org // This needs to happen before the ExtensionRegistry gets deleted, which 13145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org // happens before TearDownOnMainThread is called. 13245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unload_observer_.reset(); 13345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org } 13445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 13545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org protected: 13645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org JobDelegate delegate_; 13745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org scoped_ptr<UnloadObserver> unload_observer_; 13845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org ExtensionId id_; 13945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org GURL page_url_; 14045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}; 14145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 14245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgIN_PROC_BROWSER_TEST_F(ContentVerifierTest, FailOnRead) { 14345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org delegate_.fail_next_read(); 14445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org OpenPageAndWaitForUnload(); 14545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 14645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 14745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgIN_PROC_BROWSER_TEST_F(ContentVerifierTest, FailOnDone) { 14845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org delegate_.fail_next_done(); 14945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org OpenPageAndWaitForUnload(); 15045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 15145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 152} // namespace extensions 153