Home | History | Annotate | Download | only in debugger
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include <string>
      6 
      7 #include "base/command_line.h"
      8 #include "base/memory/ref_counted.h"
      9 #include "base/path_service.h"
     10 #include "base/strings/stringprintf.h"
     11 #include "chrome/browser/extensions/api/debugger/debugger_api.h"
     12 #include "chrome/browser/extensions/extension_apitest.h"
     13 #include "chrome/browser/extensions/extension_function_test_utils.h"
     14 #include "chrome/browser/sessions/session_tab_helper.h"
     15 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     16 #include "chrome/common/chrome_paths.h"
     17 #include "chrome/common/chrome_switches.h"
     18 #include "chrome/test/base/ui_test_utils.h"
     19 #include "extensions/browser/extension_function.h"
     20 #include "extensions/common/extension.h"
     21 #include "extensions/common/extension_builder.h"
     22 #include "extensions/common/manifest_constants.h"
     23 #include "extensions/common/switches.h"
     24 #include "extensions/common/value_builder.h"
     25 
     26 namespace extensions {
     27 
     28 class DebuggerApiTest : public ExtensionApiTest {
     29  protected:
     30   virtual ~DebuggerApiTest() {}
     31 
     32   virtual void SetUpCommandLine(base::CommandLine* command_line) OVERRIDE;
     33   virtual void SetUpOnMainThread() OVERRIDE;
     34 
     35   // Run the attach function. If |expected_error| is not empty, then the
     36   // function should fail with the error. Otherwise, the function is expected
     37   // to succeed.
     38   testing::AssertionResult RunAttachFunction(const GURL& url,
     39                                              const std::string& expected_error);
     40 
     41   const Extension* extension() const { return extension_.get(); }
     42   base::CommandLine* command_line() const { return command_line_; }
     43 
     44  private:
     45   // The command-line for the test process, preserved in order to modify
     46   // mid-test.
     47   base::CommandLine* command_line_;
     48 
     49   // A basic extension with the debugger permission.
     50   scoped_refptr<const Extension> extension_;
     51 };
     52 
     53 void DebuggerApiTest::SetUpCommandLine(base::CommandLine* command_line) {
     54   ExtensionApiTest::SetUpCommandLine(command_line);
     55   // We need to hold onto |command_line| in order to modify it during the test.
     56   command_line_ = command_line;
     57 }
     58 
     59 void DebuggerApiTest::SetUpOnMainThread() {
     60   ExtensionApiTest::SetUpOnMainThread();
     61   extension_ =
     62       ExtensionBuilder().SetManifest(
     63           DictionaryBuilder().Set("name", "debugger")
     64                              .Set("version", "0.1")
     65                              .Set("manifest_version", 2)
     66                              .Set("permissions",
     67                                   ListBuilder().Append("debugger"))).Build();
     68 }
     69 
     70 testing::AssertionResult DebuggerApiTest::RunAttachFunction(
     71     const GURL& url, const std::string& expected_error) {
     72   ui_test_utils::NavigateToURL(browser(), url);
     73   content::WebContents* web_contents =
     74       browser()->tab_strip_model()->GetActiveWebContents();
     75   int tab_id = SessionTabHelper::IdForTab(web_contents);
     76   scoped_refptr<DebuggerAttachFunction> attach_function =
     77       new DebuggerAttachFunction();
     78   attach_function->set_extension(extension_.get());
     79   std::string args = base::StringPrintf("[{\"tabId\": %d}, \"1.1\"]", tab_id);
     80 
     81   if (!expected_error.empty()) {
     82     std::string actual_error =
     83         extension_function_test_utils::RunFunctionAndReturnError(
     84             attach_function.get(), args, browser());
     85     if (actual_error != expected_error) {
     86       return testing::AssertionFailure() << "Did not get correct error: "
     87           << "expected: " << expected_error << ", found: " << actual_error;
     88     }
     89   } else {
     90     if (!RunFunction(attach_function.get(),
     91                      args,
     92                      browser(),
     93                      extension_function_test_utils::NONE)) {
     94       return testing::AssertionFailure() << "Could not run function: "
     95           << attach_function->GetError();
     96     }
     97 
     98     // Clean up and detach.
     99     scoped_refptr<DebuggerDetachFunction> detach_function =
    100         new DebuggerDetachFunction();
    101     detach_function->set_extension(extension_.get());
    102     if (!RunFunction(detach_function.get(),
    103                      base::StringPrintf("[{\"tabId\": %d}]", tab_id),
    104                      browser(),
    105                      extension_function_test_utils::NONE)) {
    106       return testing::AssertionFailure() << "Could not detach: "
    107           << detach_function->GetError();
    108     }
    109   }
    110   return testing::AssertionSuccess();
    111 }
    112 
    113 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Debugger) {
    114   ASSERT_TRUE(RunExtensionTest("debugger")) << message_;
    115 }
    116 
    117 IN_PROC_BROWSER_TEST_F(DebuggerApiTest,
    118                        DebuggerNotAllowedOnOtherExtensionPages) {
    119   // Load another arbitrary extension with an associated resource (popup.html).
    120   base::FilePath path;
    121   ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &path));
    122   path = path.AppendASCII("extensions").AppendASCII("good_unpacked");
    123   const Extension* another_extension = LoadExtension(path);
    124   ASSERT_TRUE(another_extension);
    125 
    126   GURL other_ext_url =
    127       GURL(base::StringPrintf("chrome-extension://%s/popup.html",
    128                               another_extension->id().c_str()));
    129 
    130   // This extension should not be able to access another extension.
    131   EXPECT_TRUE(RunAttachFunction(
    132       other_ext_url, manifest_errors::kCannotAccessExtensionUrl));
    133 
    134   // This extension *should* be able to debug itself.
    135   EXPECT_TRUE(RunAttachFunction(
    136                   GURL(base::StringPrintf("chrome-extension://%s/foo.html",
    137                                           extension()->id().c_str())),
    138                   std::string()));
    139 
    140   // Append extensions on chrome urls switch. The extension should now be able
    141   // to debug any extension.
    142   command_line()->AppendSwitch(switches::kExtensionsOnChromeURLs);
    143   EXPECT_TRUE(RunAttachFunction(other_ext_url, std::string()));
    144 }
    145 
    146 }  // namespace extensions
    147