diff options
author | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-19 18:05:56 +0000 |
---|---|---|
committer | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-19 18:05:56 +0000 |
commit | 8b8e7c9bce4198a4ee2865d9dfce6e8baa173ad3 (patch) | |
tree | 938304b8e1be417c1b9c73d7463dacbc1da79843 /chrome/browser/extensions | |
parent | f2c4ee3627e6039fd42bd7c0c93e902b72653449 (diff) | |
download | chromium_src-8b8e7c9bce4198a4ee2865d9dfce6e8baa173ad3.zip chromium_src-8b8e7c9bce4198a4ee2865d9dfce6e8baa173ad3.tar.gz chromium_src-8b8e7c9bce4198a4ee2865d9dfce6e8baa173ad3.tar.bz2 |
Initial version of chrome.experimental.sidebar extension API.
BUG=51084
TEST=Run interactive_ui_tests and browser_tests.
New:
- sidebar Extension API (design doc: https://docs.google.com/a/google.com/Doc?docid=0AV4Qg3xyZ8RQZGZtbWIydDJfNWc0eHJtbmRm&hl=en);
- Sidebar panel in Chrome browser view;
Original review=http://codereview.chromium.org/2836040/show
Patch by alekseys@google.com
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@56716 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/extensions')
-rw-r--r-- | chrome/browser/extensions/extension_dom_ui.cc | 13 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_dom_ui.h | 7 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_function.h | 6 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_function_dispatcher.cc | 33 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_function_dispatcher.h | 4 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_host.cc | 10 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_host.h | 6 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_sidebar_api.cc | 270 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_sidebar_api.h | 117 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_sidebar_apitest.cc | 19 |
10 files changed, 445 insertions, 40 deletions
diff --git a/chrome/browser/extensions/extension_dom_ui.cc b/chrome/browser/extensions/extension_dom_ui.cc index dd9d169..598e43b 100644 --- a/chrome/browser/extensions/extension_dom_ui.cc +++ b/chrome/browser/extensions/extension_dom_ui.cc @@ -162,16 +162,9 @@ void ExtensionDOMUI::RenderViewReused(RenderViewHost* render_view_host) { ResetExtensionBookmarkManagerEventRouter(); } -void ExtensionDOMUI::ProcessDOMUIMessage(const std::string& message, - const ListValue* content, - const GURL& source_url, - int request_id, - bool has_callback) { - extension_function_dispatcher_->HandleRequest(message, - content, - source_url, - request_id, - has_callback); +void ExtensionDOMUI::ProcessDOMUIMessage( + const ViewHostMsg_DomMessage_Params& params) { + extension_function_dispatcher_->HandleRequest(params); } Browser* ExtensionDOMUI::GetBrowser() const { diff --git a/chrome/browser/extensions/extension_dom_ui.h b/chrome/browser/extensions/extension_dom_ui.h index e0698e7..d5f146d 100644 --- a/chrome/browser/extensions/extension_dom_ui.h +++ b/chrome/browser/extensions/extension_dom_ui.h @@ -20,6 +20,7 @@ class PrefService; class Profile; class RenderViewHost; class TabContents; +struct ViewHostMsg_DomMessage_Params; // This class implements DOMUI for extensions and allows extensions to put UI in // the main tab contents area. @@ -38,11 +39,7 @@ class ExtensionDOMUI // DOMUI virtual void RenderViewCreated(RenderViewHost* render_view_host); virtual void RenderViewReused(RenderViewHost* render_view_host); - virtual void ProcessDOMUIMessage(const std::string& message, - const ListValue* content, - const GURL& source_url, - int request_id, - bool has_callback); + virtual void ProcessDOMUIMessage(const ViewHostMsg_DomMessage_Params& params); // ExtensionFunctionDispatcher::Delegate virtual Browser* GetBrowser() const; diff --git a/chrome/browser/extensions/extension_function.h b/chrome/browser/extensions/extension_function.h index 44fde69..51f25fe 100644 --- a/chrome/browser/extensions/extension_function.h +++ b/chrome/browser/extensions/extension_function.h @@ -90,6 +90,9 @@ class ExtensionFunction : public base::RefCountedThreadSafe<ExtensionFunction> { void set_include_incognito(bool include) { include_incognito_ = include; } bool include_incognito() { return include_incognito_; } + void set_user_gesture(bool user_gesture) { user_gesture_ = user_gesture; } + bool user_gesture() const { return user_gesture_; } + // Execute the API. Clients should call set_raw_args() and // set_request_id() before calling this method. Derived classes should be // ready to return raw_result() and error() before returning from this @@ -149,6 +152,9 @@ class ExtensionFunction : public base::RefCountedThreadSafe<ExtensionFunction> { // True if this callback should include information from incognito contexts. bool include_incognito_; + // True if the call was made in response of user gesture. + bool user_gesture_; + DISALLOW_COPY_AND_ASSIGN(ExtensionFunction); }; diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc index cb9e126..a2b16ee 100644 --- a/chrome/browser/extensions/extension_function_dispatcher.cc +++ b/chrome/browser/extensions/extension_function_dispatcher.cc @@ -39,6 +39,7 @@ #include "chrome/browser/extensions/extension_processes_api.h" #include "chrome/browser/extensions/extension_proxy_api.h" #include "chrome/browser/extensions/extension_rlz_module.h" +#include "chrome/browser/extensions/extension_sidebar_api.h" #include "chrome/browser/extensions/extension_tabs_module.h" #include "chrome/browser/extensions/extension_test_api.h" #if defined(OS_CHROMEOS) @@ -249,6 +250,17 @@ void FactoryRegistry::ResetFunctions() { // Proxies. RegisterFunction<UseCustomProxySettingsFunction>(); + + // Sidebar. + RegisterFunction<CollapseSidebarFunction>(); + RegisterFunction<ExpandSidebarFunction>(); + RegisterFunction<GetStateSidebarFunction>(); + RegisterFunction<HideSidebarFunction>(); + RegisterFunction<NavigateSidebarFunction>(); + RegisterFunction<SetBadgeTextSidebarFunction>(); + RegisterFunction<SetIconSidebarFunction>(); + RegisterFunction<SetTitleSidebarFunction>(); + RegisterFunction<ShowSidebarFunction>(); } void FactoryRegistry::GetAllNames(std::vector<std::string>* names) { @@ -400,20 +412,18 @@ Browser* ExtensionFunctionDispatcher::GetCurrentBrowser( return browser; } -void ExtensionFunctionDispatcher::HandleRequest(const std::string& name, - const ListValue* args, - const GURL& source_url, - int request_id, - bool has_callback) { +void ExtensionFunctionDispatcher::HandleRequest( + const ViewHostMsg_DomMessage_Params& params) { scoped_refptr<ExtensionFunction> function( - FactoryRegistry::instance()->NewFunction(name)); + FactoryRegistry::instance()->NewFunction(params.name)); function->set_dispatcher_peer(peer_); function->set_profile(profile_); function->set_extension_id(extension_id()); - function->SetArgs(args); - function->set_source_url(source_url); - function->set_request_id(request_id); - function->set_has_callback(has_callback); + function->SetArgs(¶ms.arguments); + function->set_source_url(params.source_url); + function->set_request_id(params.request_id); + function->set_has_callback(params.has_callback); + function->set_user_gesture(params.user_gesture); ExtensionsService* service = profile()->GetExtensionsService(); DCHECK(service); Extension* extension = service->GetExtensionById(extension_id(), false); @@ -421,7 +431,8 @@ void ExtensionFunctionDispatcher::HandleRequest(const std::string& name, function->set_include_incognito(service->IsIncognitoEnabled(extension)); ExtensionsQuotaService* quota = service->quota_service(); - if (quota->Assess(extension_id(), function, args, base::TimeTicks::Now())) { + if (quota->Assess(extension_id(), function, ¶ms.arguments, + base::TimeTicks::Now())) { // See crbug.com/39178. ExternalProtocolHandler::PermitLaunchUrl(); diff --git a/chrome/browser/extensions/extension_function_dispatcher.h b/chrome/browser/extensions/extension_function_dispatcher.h index e089e29..9bddecf 100644 --- a/chrome/browser/extensions/extension_function_dispatcher.h +++ b/chrome/browser/extensions/extension_function_dispatcher.h @@ -20,6 +20,7 @@ class ListValue; class Profile; class RenderViewHost; class TabContents; +struct ViewHostMsg_DomMessage_Params; // A factory function for creating new ExtensionFunction instances. typedef ExtensionFunction* (*ExtensionFunctionFactory)(); @@ -92,8 +93,7 @@ class ExtensionFunctionDispatcher { Delegate* delegate() { return delegate_; } // Handle a request to execute an extension function. - void HandleRequest(const std::string& name, const ListValue* args, - const GURL& source_url, int request_id, bool has_callback); + void HandleRequest(const ViewHostMsg_DomMessage_Params& params); // Send a response to a function. void SendResponse(ExtensionFunction* api, bool success); diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc index 7e78619..0b3cc5a 100644 --- a/chrome/browser/extensions/extension_host.cc +++ b/chrome/browser/extensions/extension_host.cc @@ -493,14 +493,10 @@ WebPreferences ExtensionHost::GetWebkitPrefs() { return webkit_prefs; } -void ExtensionHost::ProcessDOMUIMessage(const std::string& message, - const ListValue* content, - const GURL& source_url, - int request_id, - bool has_callback) { +void ExtensionHost::ProcessDOMUIMessage( + const ViewHostMsg_DomMessage_Params& params) { if (extension_function_dispatcher_.get()) { - extension_function_dispatcher_->HandleRequest( - message, content, source_url, request_id, has_callback); + extension_function_dispatcher_->HandleRequest(params); } } diff --git a/chrome/browser/extensions/extension_host.h b/chrome/browser/extensions/extension_host.h index e8fd600..c473e87 100644 --- a/chrome/browser/extensions/extension_host.h +++ b/chrome/browser/extensions/extension_host.h @@ -125,11 +125,7 @@ class ExtensionHost : public RenderViewHostDelegate, RenderViewHost* render_view_host); virtual WebPreferences GetWebkitPrefs(); - virtual void ProcessDOMUIMessage(const std::string& message, - const ListValue* content, - const GURL& source_url, - int request_id, - bool has_callback); + virtual void ProcessDOMUIMessage(const ViewHostMsg_DomMessage_Params& params); virtual void RunJavaScriptMessage(const std::wstring& message, const std::wstring& default_prompt, const GURL& frame_url, diff --git a/chrome/browser/extensions/extension_sidebar_api.cc b/chrome/browser/extensions/extension_sidebar_api.cc new file mode 100644 index 0000000..9453ac7 --- /dev/null +++ b/chrome/browser/extensions/extension_sidebar_api.cc @@ -0,0 +1,270 @@ +// Copyright (c) 2010 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/browser/extensions/extension_sidebar_api.h" + +#include "base/json/json_writer.h" +#include "base/string_number_conversions.h" +#include "base/string_util.h" +#include "base/string16.h" +#include "base/values.h" +#include "chrome/browser/extensions/extension_message_service.h" +#include "chrome/browser/extensions/extensions_service.h" +#include "chrome/browser/extensions/extension_tabs_module.h" +#include "chrome/browser/profile.h" +#include "chrome/browser/sidebar/sidebar_container.h" +#include "chrome/browser/sidebar/sidebar_manager.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/common/extensions/extension.h" +#include "chrome/common/extensions/extension_constants.h" +#include "chrome/common/extensions/extension_error_utils.h" +#include "chrome/common/render_messages.h" +#include "chrome/common/url_constants.h" +#include "ipc/ipc_message_utils.h" +#include "third_party/skia/include/core/SkBitmap.h" + +namespace { +// Errors. +const char kNoTabError[] = "No tab with id: *."; +const char kInvalidUrlError[] = "Invalid url: \"*\"."; +const char kNoCurrentWindowError[] = "No current browser window was found"; +const char kNoDefaultTabError[] = "No default tab was found"; +const char kInvalidExpandContextError[] = + "Sidebar can be expanded only in response to an explicit user gesture"; +// Keys. +const char kBadgeTextKey[] = "text"; +const char kImageDataKey[] = "imageData"; +const char kStateKey[] = "state"; +const char kTabIdKey[] = "tabId"; +const char kTitleKey[] = "title"; +const char kUrlKey[] = "url"; +// Events. +const char kOnStateChanged[] = "experimental.sidebar.onStateChanged"; +} // namespace + +namespace extension_sidebar_constants { +// Sidebar states. +const char kActiveState[] = "active"; +const char kHiddenState[] = "hidden"; +const char kShownState[] = "shown"; +} + +static GURL ResolvePossiblyRelativeURL(const std::string& url_string, + Extension* extension) { + GURL url = GURL(url_string); + if (!url.is_valid()) + url = extension->GetResourceURL(url_string); + + return url; +} + +static bool CanUseHost(Extension* extension, + const GURL& url, + std::string* error) { + if (extension->HasHostPermission(url)) + return true; + + if (error) { + *error = ExtensionErrorUtils::FormatErrorMessage( + extension_manifest_errors::kCannotAccessPage, url.spec()); + } + + return false; +} + + +// static +void ExtensionSidebarEventRouter::OnStateChanged( + Profile* profile, int tab_id, const std::string& content_id, + const std::string& state) { + DictionaryValue* details = new DictionaryValue; + details->Set(kTabIdKey, Value::CreateIntegerValue(tab_id)); + details->Set(kStateKey, Value::CreateStringValue(state)); + + ListValue args; + args.Set(0, details); + std::string json_args; + base::JSONWriter::Write(&args, false, &json_args); + + const std::string& extension_id(content_id); + profile->GetExtensionMessageService()->DispatchEventToExtension( + extension_id, kOnStateChanged, json_args, + profile->IsOffTheRecord(), GURL()); +} + + +bool SidebarFunction::RunImpl() { + if (!args_.get()) + return false; + + DictionaryValue* details = NULL; + DictionaryValue default_details; + if (args_->empty()) { + details = &default_details; + } else { + EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &details)); + } + + int tab_id; + TabContents* tab_contents = NULL; + if (details->HasKey(kTabIdKey)) { + EXTENSION_FUNCTION_VALIDATE(details->GetInteger(kTabIdKey, &tab_id)); + if (!ExtensionTabUtil::GetTabById(tab_id, profile(), include_incognito(), + NULL, NULL, &tab_contents, NULL)) { + error_ = ExtensionErrorUtils::FormatErrorMessage( + kNoTabError, base::IntToString(tab_id)); + return false; + } + } else { + Browser* browser = GetCurrentBrowser(); + if (!browser) { + error_ = kNoCurrentWindowError; + return false; + } + if (!ExtensionTabUtil::GetDefaultTab(browser, &tab_contents, &tab_id)) { + error_ = kNoDefaultTabError; + return false; + } + } + if (!tab_contents) + return false; + + std::string content_id(GetExtension()->id()); + return RunImpl(tab_contents, content_id, *details); +} + + +bool CollapseSidebarFunction::RunImpl(TabContents* tab, + const std::string& content_id, + const DictionaryValue& details) { + SidebarManager::GetInstance()->CollapseSidebar(tab, content_id); + return true; +} + +bool ExpandSidebarFunction::RunImpl(TabContents* tab, + const std::string& content_id, + const DictionaryValue& details) { + // TODO(alekseys): enable this check back when WebKit's user gesture flag + // reporting for extension calls is fixed. + // if (!user_gesture()) { + // error_ = kInvalidExpandContextError; + // return false; + // } + SidebarManager::GetInstance()->ExpandSidebar(tab, content_id); + return true; +} + +bool GetStateSidebarFunction::RunImpl(TabContents* tab, + const std::string& content_id, + const DictionaryValue& details) { + SidebarManager* manager = SidebarManager::GetInstance(); + + const char* result = extension_sidebar_constants::kHiddenState; + if (manager->GetSidebarTabContents(tab, content_id)) { + bool is_active = false; + // Sidebar is considered active only if tab is selected, sidebar UI + // is expanded and this extension's content is displayed on it. + SidebarContainer* active_sidebar = + manager->GetActiveSidebarContainerFor(tab); + // Check if sidebar UI is expanded and this extension's content + // is displayed on it. + if (active_sidebar && active_sidebar->content_id() == content_id) { + if (!details.HasKey(kTabIdKey)) { + is_active = NULL != GetCurrentBrowser(); + } else { + int tab_id; + EXTENSION_FUNCTION_VALIDATE(details.GetInteger(kTabIdKey, &tab_id)); + + // Check if this tab is selected. + Browser* browser = GetCurrentBrowser(); + TabContents* contents = NULL; + int default_tab_id = -1; + if (browser && + ExtensionTabUtil::GetDefaultTab(browser, &contents, + &default_tab_id)) { + is_active = default_tab_id == tab_id; + } + } + } + + result = is_active ? extension_sidebar_constants::kActiveState : + extension_sidebar_constants::kShownState; + } + + result_.reset(Value::CreateStringValue(result)); + return true; +} + +bool HideSidebarFunction::RunImpl(TabContents* tab, + const std::string& content_id, + const DictionaryValue& details) { + SidebarManager::GetInstance()->HideSidebar(tab, content_id); + return true; +} + +bool NavigateSidebarFunction::RunImpl(TabContents* tab, + const std::string& content_id, + const DictionaryValue& details) { + std::string url_string; + EXTENSION_FUNCTION_VALIDATE(details.GetString(kUrlKey, &url_string)); + GURL url = ResolvePossiblyRelativeURL(url_string, GetExtension()); + if (!url.is_valid()) { + error_ = ExtensionErrorUtils::FormatErrorMessage(kInvalidUrlError, + url_string); + return false; + } + if (!url.SchemeIs(chrome::kExtensionScheme) && + !CanUseHost(GetExtension(), url, &error_)) { + return false; + } + // Disallow requests outside of the requesting extension view's extension. + if (url.SchemeIs(chrome::kExtensionScheme)) { + std::string extension_id(url.host()); + if (extension_id != GetExtension()->id()) + return false; + } + + SidebarManager::GetInstance()->NavigateSidebar(tab, content_id, GURL(url)); + return true; +} + +bool SetBadgeTextSidebarFunction::RunImpl(TabContents* tab, + const std::string& content_id, + const DictionaryValue& details) { + string16 badge_text; + EXTENSION_FUNCTION_VALIDATE(details.GetString(kBadgeTextKey, &badge_text)); + SidebarManager::GetInstance()->SetSidebarBadgeText( + tab, content_id, badge_text); + return true; +} + +bool SetIconSidebarFunction::RunImpl(TabContents* tab, + const std::string& content_id, + const DictionaryValue& details) { + BinaryValue* binary; + EXTENSION_FUNCTION_VALIDATE(details.GetBinary(kImageDataKey, &binary)); + IPC::Message bitmap_pickle(binary->GetBuffer(), binary->GetSize()); + void* iter = NULL; + scoped_ptr<SkBitmap> bitmap(new SkBitmap); + EXTENSION_FUNCTION_VALIDATE( + IPC::ReadParam(&bitmap_pickle, &iter, bitmap.get())); + SidebarManager::GetInstance()->SetSidebarIcon(tab, content_id, *bitmap); + return true; +} + +bool SetTitleSidebarFunction::RunImpl(TabContents* tab, + const std::string& content_id, + const DictionaryValue& details) { + string16 title; + EXTENSION_FUNCTION_VALIDATE(details.GetString(kTitleKey, &title)); + SidebarManager::GetInstance()->SetSidebarTitle(tab, content_id, title); + return true; +} + +bool ShowSidebarFunction::RunImpl(TabContents* tab, + const std::string& content_id, + const DictionaryValue& details) { + SidebarManager::GetInstance()->ShowSidebar(tab, content_id); + return true; +} diff --git a/chrome/browser/extensions/extension_sidebar_api.h b/chrome/browser/extensions/extension_sidebar_api.h new file mode 100644 index 0000000..e4ab780 --- /dev/null +++ b/chrome/browser/extensions/extension_sidebar_api.h @@ -0,0 +1,117 @@ +// Copyright (c) 2010 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_BROWSER_EXTENSIONS_EXTENSION_SIDEBAR_API_H_ +#define CHROME_BROWSER_EXTENSIONS_EXTENSION_SIDEBAR_API_H_ + +#include <string> +#include "chrome/browser/extensions/extension_function.h" + +class DictionaryValue; +class Profile; +class RenderViewHost; +class TabContents; + +namespace extension_sidebar_constants { +extern const char kActiveState[]; +extern const char kHiddenState[]; +extern const char kShownState[]; +} // namespace extension_sidebar_constants + +// Event router class for events related to the sidebar API. +class ExtensionSidebarEventRouter { + public: + // Sidebar state changed. + static void OnStateChanged( + Profile* profile, int tab_id, const std::string& content_id, + const std::string& state); + + private: + DISALLOW_COPY_AND_ASSIGN(ExtensionSidebarEventRouter); +}; + +// Base class for sidebar function APIs. +class SidebarFunction : public SyncExtensionFunction { + public: + virtual bool RunImpl(); + private: + virtual bool RunImpl(TabContents* tab, + const std::string& content_id, + const DictionaryValue& details) = 0; +}; + +class CollapseSidebarFunction : public SidebarFunction { + private: + virtual bool RunImpl(TabContents* tab, + const std::string& content_id, + const DictionaryValue& details); + DECLARE_EXTENSION_FUNCTION_NAME("experimental.sidebar.collapse"); +}; + +class ExpandSidebarFunction : public SidebarFunction { + private: + virtual bool RunImpl(TabContents* tab, + const std::string& content_id, + const DictionaryValue& details); + DECLARE_EXTENSION_FUNCTION_NAME("experimental.sidebar.expand"); +}; + +class GetStateSidebarFunction : public SidebarFunction { + private: + virtual bool RunImpl(TabContents* tab, + const std::string& content_id, + const DictionaryValue& details); + DECLARE_EXTENSION_FUNCTION_NAME("experimental.sidebar.getState"); +}; + +class HideSidebarFunction : public SidebarFunction { + private: + virtual bool RunImpl(TabContents* tab, + const std::string& content_id, + const DictionaryValue& details); + DECLARE_EXTENSION_FUNCTION_NAME("experimental.sidebar.hide"); +}; + +class NavigateSidebarFunction : public SidebarFunction { + private: + virtual bool RunImpl(TabContents* tab, + const std::string& content_id, + const DictionaryValue& details); + DECLARE_EXTENSION_FUNCTION_NAME("experimental.sidebar.navigate"); +}; + +class SetBadgeTextSidebarFunction : public SidebarFunction { + private: + virtual bool RunImpl(TabContents* tab, + const std::string& content_id, + const DictionaryValue& details); + DECLARE_EXTENSION_FUNCTION_NAME("experimental.sidebar.setBadgeText"); +}; + +class SetIconSidebarFunction : public SidebarFunction { + private: + virtual bool RunImpl(TabContents* tab, + const std::string& content_id, + const DictionaryValue& details); + DECLARE_EXTENSION_FUNCTION_NAME("experimental.sidebar.setIcon"); +}; + +class SetTitleSidebarFunction : public SidebarFunction { + private: + virtual bool RunImpl(TabContents* tab, + const std::string& content_id, + const DictionaryValue& details); + DECLARE_EXTENSION_FUNCTION_NAME("experimental.sidebar.setTitle"); +}; + +class ShowSidebarFunction : public SidebarFunction { + private: + virtual bool RunImpl(TabContents* tab, + const std::string& content_id, + const DictionaryValue& details); + DECLARE_EXTENSION_FUNCTION_NAME("experimental.sidebar.show"); +}; + +#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_SIDEBAR_API_H_ + diff --git a/chrome/browser/extensions/extension_sidebar_apitest.cc b/chrome/browser/extensions/extension_sidebar_apitest.cc new file mode 100644 index 0000000..9d33fa0 --- /dev/null +++ b/chrome/browser/extensions/extension_sidebar_apitest.cc @@ -0,0 +1,19 @@ +// Copyright (c) 2010 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 "base/command_line.h" +#include "chrome/browser/extensions/extension_apitest.h" +#include "chrome/common/chrome_switches.h" + +class SidebarApiTest : public ExtensionApiTest { + public: + void SetUpCommandLine(CommandLine* command_line) { + ExtensionApiTest::SetUpCommandLine(command_line); + command_line->AppendSwitch(switches::kEnableExperimentalExtensionApis); + } +}; + +IN_PROC_BROWSER_TEST_F(SidebarApiTest, Sidebar) { + ASSERT_TRUE(RunExtensionTest("sidebar")) << message_; +} |