summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjyasskin@chromium.org <jyasskin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-30 02:52:07 +0000
committerjyasskin@chromium.org <jyasskin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-30 02:52:07 +0000
commit466f5e29eba257623962f12295fa994aac3b81a3 (patch)
tree978e30934ddf8d9038b5cec2306494ed057f22e0
parentc5a970ce1208bb4f10ab2bee4c631493d3f78bec (diff)
downloadchromium_src-466f5e29eba257623962f12295fa994aac3b81a3.zip
chromium_src-466f5e29eba257623962f12295fa994aac3b81a3.tar.gz
chromium_src-466f5e29eba257623962f12295fa994aac3b81a3.tar.bz2
Move the PageAction parts of ExtensionTabHelper::DidNavigateMainFrame to the PageActionController.
Test that the page actions are reset on navigation. Review URL: https://chromiumcodereview.appspot.com/10685007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@145054 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/extensions/extension_tab_helper.cc9
-rw-r--r--chrome/browser/extensions/page_action_controller.cc19
-rw-r--r--chrome/browser/extensions/page_action_controller.h9
-rw-r--r--chrome/browser/extensions/page_action_controller_unittest.cc88
-rw-r--r--chrome/browser/extensions/test_extension_system.cc5
-rw-r--r--chrome/browser/extensions/test_extension_system.h1
-rw-r--r--chrome/chrome_tests.gypi5
-rw-r--r--chrome/common/extensions/extension_builder.cc50
-rw-r--r--chrome/common/extensions/extension_builder.h49
-rw-r--r--chrome/common/extensions/value_builder.cc106
-rw-r--r--chrome/common/extensions/value_builder.h98
11 files changed, 426 insertions, 13 deletions
diff --git a/chrome/browser/extensions/extension_tab_helper.cc b/chrome/browser/extensions/extension_tab_helper.cc
index 3195913..577f048 100644
--- a/chrome/browser/extensions/extension_tab_helper.cc
+++ b/chrome/browser/extensions/extension_tab_helper.cc
@@ -154,15 +154,6 @@ void ExtensionTabHelper::DidNavigateMainFrame(
content::Source<ExtensionAction>(browser_action),
content::NotificationService::NoDetails());
}
-
- // TODO(jyasskin): Have PageActionController observe DidNavigateMainFrame,
- // and move this code there.
- ExtensionAction* page_action = (*it)->page_action();
- if (page_action) {
- page_action->ClearAllValuesForTab(
- tab_contents_->restore_tab_helper()->session_id().id());
- location_bar_controller()->NotifyChange();
- }
}
}
diff --git a/chrome/browser/extensions/page_action_controller.cc b/chrome/browser/extensions/page_action_controller.cc
index 7d4877a..2d310c2 100644
--- a/chrome/browser/extensions/page_action_controller.cc
+++ b/chrome/browser/extensions/page_action_controller.cc
@@ -19,7 +19,8 @@
namespace extensions {
PageActionController::PageActionController(TabContents* tab_contents)
- : tab_contents_(tab_contents) {}
+ : content::WebContentsObserver(tab_contents->web_contents()),
+ tab_contents_(tab_contents) {}
PageActionController::~PageActionController() {}
@@ -81,6 +82,22 @@ void PageActionController::NotifyChange() {
content::INVALIDATE_TYPE_PAGE_ACTIONS);
}
+void PageActionController::DidNavigateMainFrame(
+ const content::LoadCommittedDetails& details,
+ const content::FrameNavigateParams& params) {
+ const std::vector<ExtensionAction*> current_actions = GetCurrentActions();
+
+ if (current_actions.empty())
+ return;
+
+ for (size_t i = 0; i < current_actions.size(); ++i) {
+ current_actions[i]->ClearAllValuesForTab(
+ tab_contents_->extension_tab_helper()->tab_id());
+ }
+
+ NotifyChange();
+}
+
ExtensionService* PageActionController::GetExtensionService() const {
return ExtensionSystem::Get(tab_contents_->profile())->extension_service();
}
diff --git a/chrome/browser/extensions/page_action_controller.h b/chrome/browser/extensions/page_action_controller.h
index e9afaf0..8c9941d 100644
--- a/chrome/browser/extensions/page_action_controller.h
+++ b/chrome/browser/extensions/page_action_controller.h
@@ -11,6 +11,7 @@
#include "base/observer_list.h"
#include "chrome/browser/extensions/location_bar_controller.h"
+#include "content/public/browser/web_contents_observer.h"
class ExtensionService;
class TabContents;
@@ -19,7 +20,8 @@ namespace extensions {
// A LocationBarController which populates the location bar with icons based
// on the page_action extension API.
-class PageActionController : public LocationBarController {
+class PageActionController : public LocationBarController,
+ public content::WebContentsObserver {
public:
explicit PageActionController(TabContents* tab_contents);
virtual ~PageActionController();
@@ -30,6 +32,11 @@ class PageActionController : public LocationBarController {
int mouse_button) OVERRIDE;
virtual void NotifyChange() OVERRIDE;
+ // content::WebContentsObserver implementation.
+ virtual void DidNavigateMainFrame(
+ const content::LoadCommittedDetails& details,
+ const content::FrameNavigateParams& params) OVERRIDE;
+
private:
// Gets the ExtensionService for |tab_contents_|.
ExtensionService* GetExtensionService() const;
diff --git a/chrome/browser/extensions/page_action_controller_unittest.cc b/chrome/browser/extensions/page_action_controller_unittest.cc
new file mode 100644
index 0000000..94288d0
--- /dev/null
+++ b/chrome/browser/extensions/page_action_controller_unittest.cc
@@ -0,0 +1,88 @@
+// Copyright (c) 2012 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.
+
+#include <string>
+
+#include "base/command_line.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_tab_helper.h"
+#include "chrome/browser/extensions/page_action_controller.h"
+#include "chrome/browser/extensions/test_extension_system.h"
+#include "chrome/browser/ui/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/tab_contents/test_tab_contents.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/extension_builder.h"
+#include "chrome/common/extensions/value_builder.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/test/test_browser_thread.h"
+
+using content::BrowserThread;
+
+namespace extensions {
+namespace {
+
+class PageActionControllerTest : public TabContentsTestHarness {
+ public:
+ PageActionControllerTest()
+ : ui_thread_(BrowserThread::UI, MessageLoop::current()) {
+ }
+
+ virtual void SetUp() {
+ TabContentsTestHarness::SetUp();
+ // Create an ExtensionService so the PageActionController can find its
+ // extensions.
+ CommandLine command_line(CommandLine::NO_PROGRAM);
+ extension_service_ =
+ static_cast<TestExtensionSystem*>(
+ ExtensionSystem::Get(tab_contents()->profile()))->
+ CreateExtensionService(
+ &command_line, FilePath(), false);
+ }
+
+ protected:
+ int tab_id() {
+ return tab_contents()->extension_tab_helper()->tab_id();
+ }
+
+ ExtensionService* extension_service_;
+
+ private:
+ content::TestBrowserThread ui_thread_;
+};
+
+TEST_F(PageActionControllerTest, NavigationClearsState) {
+ scoped_refptr<const Extension> extension =
+ ExtensionBuilder()
+ .SetManifest(DictionaryBuilder()
+ .Set("name", "Extension with page action")
+ .Set("version", "1.0.0")
+ .Set("manifest_version", 2)
+ .Set("permissions", ListBuilder()
+ .Append("tabs"))
+ .Set("page_action", DictionaryBuilder()
+ .Set("default_title", "Hello")))
+ .Build();
+ extension_service_->AddExtension(extension);
+
+ NavigateAndCommit(GURL("http://www.google.com"));
+
+ extension->page_action()->SetTitle(tab_id(), "Goodbye");
+ extension->page_action()->SetPopupUrl(
+ tab_id(), extension->GetResourceURL("popup.html"));
+
+ EXPECT_EQ("Goodbye", extension->page_action()->GetTitle(tab_id()));
+ EXPECT_EQ(extension->GetResourceURL("popup.html"),
+ extension->page_action()->GetPopupUrl(tab_id()));
+
+ // Should discard the settings, and go back to the defaults.
+ NavigateAndCommit(GURL("http://www.yahoo.com"));
+
+ EXPECT_EQ("Hello", extension->page_action()->GetTitle(tab_id()));
+ EXPECT_EQ(GURL(), extension->page_action()->GetPopupUrl(tab_id()));
+};
+
+} // namespace
+} // namespace extensions
diff --git a/chrome/browser/extensions/test_extension_system.cc b/chrome/browser/extensions/test_extension_system.cc
index 8fbb699..51543a3 100644
--- a/chrome/browser/extensions/test_extension_system.cc
+++ b/chrome/browser/extensions/test_extension_system.cc
@@ -22,7 +22,8 @@
TestExtensionSystem::TestExtensionSystem(Profile* profile)
- : profile_(profile) {
+ : profile_(profile),
+ info_map_(new ExtensionInfoMap()) {
}
TestExtensionSystem::~TestExtensionSystem() {
@@ -111,7 +112,7 @@ extensions::StateStore* TestExtensionSystem::state_store() {
}
ExtensionInfoMap* TestExtensionSystem::info_map() {
- return NULL;
+ return info_map_.get();
}
extensions::LazyBackgroundTaskQueue*
diff --git a/chrome/browser/extensions/test_extension_system.h b/chrome/browser/extensions/test_extension_system.h
index 630e857..96459e3d 100644
--- a/chrome/browser/extensions/test_extension_system.h
+++ b/chrome/browser/extensions/test_extension_system.h
@@ -71,6 +71,7 @@ class TestExtensionSystem : public ExtensionSystem {
scoped_ptr<extensions::ManagementPolicy> management_policy_;
scoped_ptr<ExtensionProcessManager> extension_process_manager_;
scoped_ptr<extensions::AlarmManager> alarm_manager_;
+ scoped_refptr<ExtensionInfoMap> info_map_;
};
#endif // CHROME_BROWSER_EXTENSIONS_TEST_EXTENSION_SYSTEM_H_
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 03d441a..835a32e 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -177,6 +177,10 @@
'browser/ui/panels/test_panel_mouse_watcher.h',
'browser/ui/tab_contents/test_tab_contents.cc',
'browser/ui/tab_contents/test_tab_contents.h',
+ 'common/extensions/extension_builder.cc',
+ 'common/extensions/extension_builder.h',
+ 'common/extensions/value_builder.cc',
+ 'common/extensions/value_builder.h',
'common/net/gaia/mock_url_fetcher_factory.h',
'common/pref_store_observer_mock.cc',
'common/pref_store_observer_mock.h',
@@ -1239,6 +1243,7 @@
'browser/extensions/extension_warning_set_unittest.cc',
'browser/extensions/extensions_quota_service_unittest.cc',
'browser/extensions/external_policy_extension_loader_unittest.cc',
+ 'browser/extensions/page_action_controller_unittest.cc',
'browser/extensions/permissions_updater_unittest.cc',
'browser/extensions/file_reader_unittest.cc',
'browser/extensions/image_loading_tracker_unittest.cc',
diff --git a/chrome/common/extensions/extension_builder.cc b/chrome/common/extensions/extension_builder.cc
new file mode 100644
index 0000000..a27a204
--- /dev/null
+++ b/chrome/common/extensions/extension_builder.cc
@@ -0,0 +1,50 @@
+// Copyright (c) 2012 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.
+
+#include "chrome/common/extensions/extension_builder.h"
+
+#include "chrome/common/extensions/extension.h"
+
+namespace extensions {
+
+ExtensionBuilder::ExtensionBuilder()
+ : location_(Extension::LOAD),
+ flags_(Extension::NO_FLAGS) {
+}
+ExtensionBuilder::~ExtensionBuilder() {}
+
+scoped_refptr<Extension> ExtensionBuilder::Build() {
+ std::string error;
+ scoped_refptr<Extension> extension = Extension::Create(
+ path_,
+ location_,
+ *manifest_,
+ flags_,
+ &error);
+ CHECK_EQ("", error);
+ return extension;
+}
+
+ExtensionBuilder& ExtensionBuilder::SetPath(const FilePath& path) {
+ path_ = path_;
+ return *this;
+}
+
+ExtensionBuilder& ExtensionBuilder::SetLocation(Extension::Location location) {
+ location_ = location;
+ return *this;
+}
+
+ExtensionBuilder& ExtensionBuilder::SetManifest(
+ scoped_ptr<DictionaryValue> manifest) {
+ manifest_ = manifest.Pass();
+ return *this;
+}
+
+ExtensionBuilder& ExtensionBuilder::AddFlags(int init_from_value_flags) {
+ flags_ |= init_from_value_flags;
+ return *this;
+}
+
+} // namespace extensions
diff --git a/chrome/common/extensions/extension_builder.h b/chrome/common/extensions/extension_builder.h
new file mode 100644
index 0000000..c50b180
--- /dev/null
+++ b/chrome/common/extensions/extension_builder.h
@@ -0,0 +1,49 @@
+// Copyright (c) 2012 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.
+
+#ifndef CHROME_COMMON_EXTENSIONS_EXTENSION_BUILDER_H_
+#define CHROME_COMMON_EXTENSIONS_EXTENSION_BUILDER_H_
+#pragma once
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/common/extensions/value_builder.h"
+
+namespace extensions {
+
+// An easier way to create extensions than Extension::Create. The
+// constructor sets up some defaults which are customized using the
+// methods. The only method that must be called is SetManifest().
+class ExtensionBuilder {
+ public:
+ ExtensionBuilder();
+ ~ExtensionBuilder();
+
+ // Can only be called once, after which it's invalid to use the builder.
+ // CHECKs that the extension was created successfully.
+ scoped_refptr<Extension> Build();
+
+ // Defaults to FilePath().
+ ExtensionBuilder& SetPath(const FilePath& path);
+ // Defaults to Extension::LOAD.
+ ExtensionBuilder& SetLocation(Extension::Location location);
+
+ ExtensionBuilder& SetManifest(scoped_ptr<base::DictionaryValue> manifest);
+ ExtensionBuilder& SetManifest(DictionaryBuilder& manifest_builder) {
+ return SetManifest(manifest_builder.Build());
+ }
+
+ ExtensionBuilder& AddFlags(int init_from_value_flags);
+
+ private:
+ FilePath path_;
+ Extension::Location location_;
+ scoped_ptr<base::DictionaryValue> manifest_;
+ int flags_;
+};
+
+} // namespace extensions
+
+#endif // CHROME_COMMON_EXTENSIONS_EXTENSION_BUILDER_H_
diff --git a/chrome/common/extensions/value_builder.cc b/chrome/common/extensions/value_builder.cc
new file mode 100644
index 0000000..6e3ebaf
--- /dev/null
+++ b/chrome/common/extensions/value_builder.cc
@@ -0,0 +1,106 @@
+// Copyright (c) 2012 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.
+
+#include "chrome/common/extensions/value_builder.h"
+
+#include "base/values.h"
+
+using base::DictionaryValue;
+using base::ListValue;
+
+namespace extensions {
+
+// DictionaryBuilder
+
+DictionaryBuilder::DictionaryBuilder() : dict_(new DictionaryValue) {}
+
+DictionaryBuilder::DictionaryBuilder(const DictionaryValue& init)
+ : dict_(init.DeepCopy()) {}
+
+DictionaryBuilder::~DictionaryBuilder() {}
+
+DictionaryBuilder& DictionaryBuilder::Set(const std::string& path,
+ int in_value) {
+ dict_->SetInteger(path, in_value);
+ return *this;
+}
+
+DictionaryBuilder& DictionaryBuilder::Set(const std::string& path,
+ double in_value) {
+ dict_->SetDouble(path, in_value);
+ return *this;
+}
+
+DictionaryBuilder& DictionaryBuilder::Set(const std::string& path,
+ const std::string& in_value) {
+ dict_->SetString(path, in_value);
+ return *this;
+}
+
+DictionaryBuilder& DictionaryBuilder::Set(const std::string& path,
+ const string16& in_value) {
+ dict_->SetString(path, in_value);
+ return *this;
+}
+
+DictionaryBuilder& DictionaryBuilder::Set(const std::string& path,
+ DictionaryBuilder& in_value) {
+ dict_->Set(path, in_value.Build().release());
+ return *this;
+}
+
+DictionaryBuilder& DictionaryBuilder::Set(const std::string& path,
+ ListBuilder& in_value) {
+ dict_->Set(path, in_value.Build().release());
+ return *this;
+}
+
+DictionaryBuilder& DictionaryBuilder::SetBoolean(
+ const std::string& path, bool in_value) {
+ dict_->SetBoolean(path, in_value);
+ return *this;
+}
+
+// ListBuilder
+
+ListBuilder::ListBuilder() : list_(new ListValue) {}
+ListBuilder::ListBuilder(const ListValue& init) : list_(init.DeepCopy()) {}
+ListBuilder::~ListBuilder() {}
+
+ListBuilder& ListBuilder::Append(int in_value) {
+ list_->Append(Value::CreateIntegerValue(in_value));
+ return *this;
+}
+
+ListBuilder& ListBuilder::Append(double in_value) {
+ list_->Append(Value::CreateDoubleValue(in_value));
+ return *this;
+}
+
+ListBuilder& ListBuilder::Append(const std::string& in_value) {
+ list_->Append(Value::CreateStringValue(in_value));
+ return *this;
+}
+
+ListBuilder& ListBuilder::Append(const string16& in_value) {
+ list_->Append(Value::CreateStringValue(in_value));
+ return *this;
+}
+
+ListBuilder& ListBuilder::Append(DictionaryBuilder& in_value) {
+ list_->Append(in_value.Build().release());
+ return *this;
+}
+
+ListBuilder& ListBuilder::Append(ListBuilder& in_value) {
+ list_->Append(in_value.Build().release());
+ return *this;
+}
+
+ListBuilder& ListBuilder::AppendBoolean(bool in_value) {
+ list_->Append(Value::CreateBooleanValue(in_value));
+ return *this;
+}
+
+} // namespace extensions
diff --git a/chrome/common/extensions/value_builder.h b/chrome/common/extensions/value_builder.h
new file mode 100644
index 0000000..658d7d2
--- /dev/null
+++ b/chrome/common/extensions/value_builder.h
@@ -0,0 +1,98 @@
+// Copyright (c) 2012 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.
+
+// This file provides a builders for DictionaryValue and ListValue. These
+// aren't specific to extensions and could move up to base/ if there's interest
+// from other sub-projects.
+//
+// The general pattern is to write:
+//
+// scoped_ptr<BuiltType> result(FooBuilder()
+// .Set(args)
+// .Set(args)
+// .Build());
+//
+// For methods that take other built types, you can pass the builder directly
+// to the setter without calling Build():
+//
+// DictionaryBuilder().Set("key", ListBuilder()
+// .Append("foo").Append("bar") /* No .Build() */);
+//
+// Because of limitations in C++03, and to avoid extra copies, you can't pass a
+// just-constructed Builder into another Builder's method without setting at
+// least 1 field.
+//
+// The Build() method invalidates its builder, and returns ownership of the
+// built value.
+//
+// These objects are intended to be used as temporaries rather than stored
+// anywhere, so the use of non-const reference parameters is likely to cause
+// less confusion than usual.
+
+#ifndef CHROME_COMMON_EXTENSIONS_VALUE_BUILDER_H_
+#define CHROME_COMMON_EXTENSIONS_VALUE_BUILDER_H_
+#pragma once
+
+#include <string>
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/string16.h"
+#include "base/values.h"
+
+namespace extensions {
+
+class ListBuilder;
+
+class DictionaryBuilder {
+ public:
+ DictionaryBuilder();
+ explicit DictionaryBuilder(const base::DictionaryValue& init);
+ ~DictionaryBuilder();
+
+ // Can only be called once, after which it's invalid to use the builder.
+ scoped_ptr<base::DictionaryValue> Build() { return dict_.Pass(); }
+
+ DictionaryBuilder& Set(const std::string& path, int in_value);
+ DictionaryBuilder& Set(const std::string& path, double in_value);
+ DictionaryBuilder& Set(const std::string& path, const std::string& in_value);
+ DictionaryBuilder& Set(const std::string& path, const string16& in_value);
+ DictionaryBuilder& Set(const std::string& path, DictionaryBuilder& in_value);
+ DictionaryBuilder& Set(const std::string& path, ListBuilder& in_value);
+
+ // Named differently because overload resolution is too eager to
+ // convert implicitly to bool.
+ DictionaryBuilder& SetBoolean(const std::string& path, bool in_value);
+
+ private:
+ scoped_ptr<base::DictionaryValue> dict_;
+};
+
+class ListBuilder {
+ public:
+ ListBuilder();
+ explicit ListBuilder(const base::ListValue& init);
+ ~ListBuilder();
+
+ // Can only be called once, after which it's invalid to use the builder.
+ scoped_ptr<base::ListValue> Build() { return list_.Pass(); }
+
+ ListBuilder& Append(int in_value);
+ ListBuilder& Append(double in_value);
+ ListBuilder& Append(const std::string& in_value);
+ ListBuilder& Append(const string16& in_value);
+ ListBuilder& Append(DictionaryBuilder& in_value);
+ ListBuilder& Append(ListBuilder& in_value);
+
+ // Named differently because overload resolution is too eager to
+ // convert implicitly to bool.
+ ListBuilder& AppendBoolean(bool in_value);
+
+ private:
+ scoped_ptr<base::ListValue> list_;
+};
+
+} // namespace extensions
+
+#endif // CHROME_COMMON_EXTENSIONS_VALUE_BUILDER_H_