summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/values.h5
-rw-r--r--chrome/app/generated_resources.grd3
-rw-r--r--chrome/browser/browser.cc3
-rw-r--r--chrome/browser/browser.h4
-rw-r--r--chrome/browser/browser_process.h2
-rw-r--r--chrome/browser/browser_process_impl.cc15
-rw-r--r--chrome/browser/browser_process_impl.h5
-rw-r--r--chrome/browser/browser_window.h3
-rw-r--r--chrome/browser/dom_ui/dom_ui.cc11
-rw-r--r--chrome/browser/dom_ui/dom_ui.h9
-rw-r--r--chrome/browser/extensions/extension_dom_ui.cc13
-rw-r--r--chrome/browser/extensions/extension_dom_ui.h7
-rw-r--r--chrome/browser/extensions/extension_function.h6
-rw-r--r--chrome/browser/extensions/extension_function_dispatcher.cc33
-rw-r--r--chrome/browser/extensions/extension_function_dispatcher.h4
-rw-r--r--chrome/browser/extensions/extension_host.cc10
-rw-r--r--chrome/browser/extensions/extension_host.h6
-rw-r--r--chrome/browser/extensions/extension_sidebar_api.cc270
-rw-r--r--chrome/browser/extensions/extension_sidebar_api.h117
-rw-r--r--chrome/browser/extensions/extension_sidebar_apitest.cc19
-rw-r--r--chrome/browser/gtk/view_id_util_browsertest.cc4
-rw-r--r--chrome/browser/notifications/balloon_host.cc10
-rw-r--r--chrome/browser/notifications/balloon_host.h6
-rw-r--r--chrome/browser/renderer_host/render_view_host.cc34
-rw-r--r--chrome/browser/renderer_host/render_view_host.h6
-rw-r--r--chrome/browser/renderer_host/render_view_host_delegate.h8
-rw-r--r--chrome/browser/sidebar/sidebar_container.cc73
-rw-r--r--chrome/browser/sidebar/sidebar_container.h141
-rw-r--r--chrome/browser/sidebar/sidebar_manager.cc323
-rw-r--r--chrome/browser/sidebar/sidebar_manager.h156
-rw-r--r--chrome/browser/sidebar/sidebar_test.cc177
-rw-r--r--chrome/browser/tab_contents/background_contents.cc9
-rw-r--r--chrome/browser/tab_contents/background_contents.h6
-rw-r--r--chrome/browser/tab_contents/tab_contents.cc13
-rw-r--r--chrome/browser/tab_contents/tab_contents.h7
-rw-r--r--chrome/browser/view_ids.h6
-rw-r--r--chrome/browser/views/dropdown_bar_host.cc2
-rw-r--r--chrome/browser/views/find_bar_host.cc5
-rw-r--r--chrome/browser/views/frame/browser_view.cc155
-rw-r--r--chrome/browser/views/frame/browser_view.h52
-rw-r--r--chrome/browser/views/frame/browser_view_layout.cc13
-rw-r--r--chrome/chrome_browser.gypi6
-rw-r--r--chrome/chrome_tests.gypi1
-rw-r--r--chrome/common/extensions/api/extension_api.json241
-rw-r--r--chrome/common/extensions/docs/experimental.html1
-rw-r--r--chrome/common/extensions/docs/experimental.sidebar.html2415
-rw-r--r--chrome/common/notification_type.h5
-rw-r--r--chrome/common/pref_names.cc2
-rw-r--r--chrome/common/pref_names.h2
-rw-r--r--chrome/common/render_messages.h60
-rw-r--r--chrome/common/render_messages_internal.h8
-rw-r--r--chrome/renderer/extensions/extension_process_bindings.cc49
-rw-r--r--chrome/renderer/render_view.cc14
-rw-r--r--chrome/renderer/render_view.h5
-rw-r--r--chrome/renderer/resources/extension_process_bindings.js43
-rw-r--r--chrome/renderer/resources/renderer_extension_bindings.js1
-rw-r--r--chrome/test/data/extensions/api_test/sidebar/manifest.json7
-rw-r--r--chrome/test/data/extensions/api_test/sidebar/simple_page.html6
-rw-r--r--chrome/test/data/extensions/api_test/sidebar/test.html1
-rw-r--r--chrome/test/data/extensions/api_test/sidebar/test.js226
-rw-r--r--chrome/test/interactive_ui/interactive_ui_tests.gypi2
-rw-r--r--chrome/test/testing_browser_process.h4
62 files changed, 4654 insertions, 196 deletions
diff --git a/base/values.h b/base/values.h
index b729b52..a70b0c8 100644
--- a/base/values.h
+++ b/base/values.h
@@ -418,6 +418,11 @@ class ListValue : public Value {
// Returns true if successful, or false if the index was out of range.
bool Insert(size_t index, Value* in_value);
+ // Swaps contents with the |other| list.
+ void Swap(ListValue* other) {
+ list_.swap(other->list_);
+ }
+
// Iteration
typedef ValueVector::iterator iterator;
typedef ValueVector::const_iterator const_iterator;
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 3ea6fdb..92f206f 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -4020,6 +4020,9 @@ Keep your key file in a safe place. You will need it to create new versions of y
<message name="IDS_ACCNAME_WEB_CONTENTS" desc="The accessible name for the web contents.">
Web Contents
</message>
+ <message name="IDS_ACCNAME_SIDE_BAR" desc="The accessible name for the side bar.">
+ Sidebar
+ </message>
<!-- Browser Hung Plugin Detector -->
<message name="IDS_UNKNOWN_PLUGIN_NAME" desc="Name for a plugin whose name could not be determined">
diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc
index 6cad802..e07d701 100644
--- a/chrome/browser/browser.cc
+++ b/chrome/browser/browser.cc
@@ -1163,7 +1163,7 @@ bool Browser::SupportsWindowFeatureImpl(WindowFeature feature,
window_->IsFullscreen();
#endif
- unsigned int features = FEATURE_INFOBAR;
+ unsigned int features = FEATURE_INFOBAR | FEATURE_SIDEBAR;
#if !defined(OS_CHROMEOS)
// Chrome OS opens a FileBrowse pop up instead of using download shelf.
@@ -1922,6 +1922,7 @@ void Browser::RegisterPrefs(PrefService* prefs) {
prefs->RegisterIntegerPref(prefs::kOptionsWindowLastTabIndex, 0);
prefs->RegisterIntegerPref(prefs::kDevToolsSplitLocation, -1);
prefs->RegisterDictionaryPref(prefs::kPreferencesWindowPlacement);
+ prefs->RegisterIntegerPref(prefs::kExtensionSidebarWidth, -1);
}
// static
diff --git a/chrome/browser/browser.h b/chrome/browser/browser.h
index 17d7955..12def80 100644
--- a/chrome/browser/browser.h
+++ b/chrome/browser/browser.h
@@ -8,6 +8,7 @@
#include <map>
#include <set>
+#include <string>
#include <vector>
#include "base/basictypes.h"
@@ -86,7 +87,8 @@ class Browser : public TabStripModelDelegate,
FEATURE_LOCATIONBAR = 8,
FEATURE_BOOKMARKBAR = 16,
FEATURE_INFOBAR = 32,
- FEATURE_DOWNLOADSHELF = 64
+ FEATURE_SIDEBAR = 64,
+ FEATURE_DOWNLOADSHELF = 128
};
// Maximized state on creation.
diff --git a/chrome/browser/browser_process.h b/chrome/browser/browser_process.h
index a853c74..0eeb08d 100644
--- a/chrome/browser/browser_process.h
+++ b/chrome/browser/browser_process.h
@@ -29,6 +29,7 @@ class NotificationUIManager;
class PrefService;
class ProfileManager;
class ResourceDispatcherHost;
+class SidebarManager;
class TabCloseableStateWatcher;
class ThumbnailGenerator;
@@ -63,6 +64,7 @@ class BrowserProcess {
virtual ProfileManager* profile_manager() = 0;
virtual PrefService* local_state() = 0;
virtual DevToolsManager* devtools_manager() = 0;
+ virtual SidebarManager* sidebar_manager() = 0;
virtual Clipboard* clipboard() = 0;
// Returns the manager for desktop notifications.
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index f314388..ff43685 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -43,6 +43,7 @@
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
#include "chrome/browser/safe_browsing/safe_browsing_service.h"
+#include "chrome/browser/sidebar/sidebar_manager.h"
#include "chrome/browser/tab_closeable_state_watcher.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
@@ -85,6 +86,7 @@ BrowserProcessImpl::BrowserProcessImpl(const CommandLine& command_line)
created_icon_manager_(false),
created_debugger_wrapper_(false),
created_devtools_manager_(false),
+ created_sidebar_manager_(false),
created_notification_ui_manager_(false),
module_ref_count_(0),
did_start_(false),
@@ -346,6 +348,13 @@ DevToolsManager* BrowserProcessImpl::devtools_manager() {
return devtools_manager_.get();
}
+SidebarManager* BrowserProcessImpl::sidebar_manager() {
+ DCHECK(CalledOnValidThread());
+ if (!created_sidebar_manager_)
+ CreateSidebarManager();
+ return sidebar_manager_.get();
+}
+
Clipboard* BrowserProcessImpl::clipboard() {
DCHECK(CalledOnValidThread());
return clipboard_.get();
@@ -617,6 +626,12 @@ void BrowserProcessImpl::CreateDevToolsManager() {
devtools_manager_ = new DevToolsManager();
}
+void BrowserProcessImpl::CreateSidebarManager() {
+ DCHECK(sidebar_manager_.get() == NULL);
+ created_sidebar_manager_ = true;
+ sidebar_manager_ = new SidebarManager();
+}
+
void BrowserProcessImpl::CreateGoogleURLTracker() {
DCHECK(google_url_tracker_.get() == NULL);
scoped_ptr<GoogleURLTracker> google_url_tracker(new GoogleURLTracker);
diff --git a/chrome/browser/browser_process_impl.h b/chrome/browser/browser_process_impl.h
index 9118ff6..0ae2de6 100644
--- a/chrome/browser/browser_process_impl.h
+++ b/chrome/browser/browser_process_impl.h
@@ -49,6 +49,7 @@ class BrowserProcessImpl : public BrowserProcess, public NonThreadSafe {
virtual ProfileManager* profile_manager();
virtual PrefService* local_state();
virtual DevToolsManager* devtools_manager();
+ virtual SidebarManager* sidebar_manager();
virtual Clipboard* clipboard();
virtual NotificationUIManager* notification_ui_manager();
virtual IconManager* icon_manager();
@@ -100,6 +101,7 @@ class BrowserProcessImpl : public BrowserProcess, public NonThreadSafe {
void CreateIconManager();
void CreateDebuggerWrapper(int port, bool useHttp);
void CreateDevToolsManager();
+ void CreateSidebarManager();
void CreateGoogleURLTracker();
void CreateIntranetRedirectDetector();
void CreateNotificationUIManager();
@@ -150,6 +152,9 @@ class BrowserProcessImpl : public BrowserProcess, public NonThreadSafe {
bool created_devtools_manager_;
scoped_refptr<DevToolsManager> devtools_manager_;
+ bool created_sidebar_manager_;
+ scoped_refptr<SidebarManager> sidebar_manager_;
+
scoped_ptr<Clipboard> clipboard_;
// Manager for desktop notification UI.
diff --git a/chrome/browser/browser_window.h b/chrome/browser/browser_window.h
index 6554713..98cd042 100644
--- a/chrome/browser/browser_window.h
+++ b/chrome/browser/browser_window.h
@@ -349,6 +349,9 @@ class BrowserWindowTesting {
// Returns the TabContentsContainer.
virtual views::View* GetTabContentsContainerView() const = 0;
+ // Returns the TabContentsContainer.
+ virtual views::View* GetSidebarContainerView() const = 0;
+
// Returns the ToolbarView.
virtual ToolbarView* GetToolbarView() const = 0;
#endif
diff --git a/chrome/browser/dom_ui/dom_ui.cc b/chrome/browser/dom_ui/dom_ui.cc
index 118e262..a5b965a 100644
--- a/chrome/browser/dom_ui/dom_ui.cc
+++ b/chrome/browser/dom_ui/dom_ui.cc
@@ -16,6 +16,7 @@
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/tab_contents/tab_contents_view.h"
#include "chrome/common/bindings_policy.h"
+#include "chrome/common/render_messages.h"
namespace {
@@ -53,19 +54,15 @@ DOMUI::~DOMUI() {
// DOMUI, public: -------------------------------------------------------------
-void DOMUI::ProcessDOMUIMessage(const std::string& message,
- const ListValue* content,
- const GURL& source_url,
- int request_id,
- bool has_callback) {
+void DOMUI::ProcessDOMUIMessage(const ViewHostMsg_DomMessage_Params& params) {
// Look up the callback for this message.
MessageCallbackMap::const_iterator callback =
- message_callbacks_.find(message);
+ message_callbacks_.find(params.name);
if (callback == message_callbacks_.end())
return;
// Forward this message and content on.
- callback->second->Run(content);
+ callback->second->Run(&params.arguments);
}
void DOMUI::CallJavascriptFunction(const std::wstring& function_name) {
diff --git a/chrome/browser/dom_ui/dom_ui.h b/chrome/browser/dom_ui/dom_ui.h
index 66c5455..d805921 100644
--- a/chrome/browser/dom_ui/dom_ui.h
+++ b/chrome/browser/dom_ui/dom_ui.h
@@ -20,9 +20,10 @@ class GURL;
class ListValue;
class Profile;
class RenderViewHost;
-class Value;
class TabContents;
class ThemeProvider;
+class Value;
+struct ViewHostMsg_DomMessage_Params;
// A DOMUI sets up the datasources and message handlers for a given HTML-based
// UI. It is contained by a DOMUIManager.
@@ -42,11 +43,7 @@ class DOMUI {
virtual void RenderViewReused(RenderViewHost* render_view_host) {}
// Called from TabContents.
- 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);
// Used by DOMMessageHandlers.
typedef Callback1<const Value*>::Type MessageCallback;
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(&params.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, &params.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_;
+}
diff --git a/chrome/browser/gtk/view_id_util_browsertest.cc b/chrome/browser/gtk/view_id_util_browsertest.cc
index b80fb02..be4f38c 100644
--- a/chrome/browser/gtk/view_id_util_browsertest.cc
+++ b/chrome/browser/gtk/view_id_util_browsertest.cc
@@ -38,7 +38,9 @@ IN_PROC_BROWSER_TEST_F(ViewIDTest, Basic) {
i == VIEW_ID_INFO_BAR_CONTAINER ||
i == VIEW_ID_DOWNLOAD_SHELF ||
i == VIEW_ID_BOOKMARK_BAR_ELEMENT ||
- i == VIEW_ID_TAB) {
+ i == VIEW_ID_TAB ||
+ i == VIEW_ID_SIDE_BAR_CONTAINER ||
+ i == VIEW_ID_SIDE_BAR_SPLIT) {
continue;
}
diff --git a/chrome/browser/notifications/balloon_host.cc b/chrome/browser/notifications/balloon_host.cc
index 621fa7e..85022dc 100644
--- a/chrome/browser/notifications/balloon_host.cc
+++ b/chrome/browser/notifications/balloon_host.cc
@@ -76,14 +76,10 @@ void BalloonHost::RenderViewGone(RenderViewHost* render_view_host) {
Close(render_view_host);
}
-void BalloonHost::ProcessDOMUIMessage(const std::string& message,
- const ListValue* content,
- const GURL& source_url,
- int request_id,
- bool has_callback) {
+void BalloonHost::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/notifications/balloon_host.h b/chrome/browser/notifications/balloon_host.h
index 45d5c2d..77e52ee 100644
--- a/chrome/browser/notifications/balloon_host.h
+++ b/chrome/browser/notifications/balloon_host.h
@@ -74,11 +74,7 @@ class BalloonHost : public RenderViewHostDelegate,
virtual RenderViewHostDelegate::View* GetViewDelegate() {
return this;
}
- 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);
// RenderViewHostDelegate::View methods. Only the ones for opening new
// windows are currently implemented.
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc
index 9f1ea87..0ba65d6 100644
--- a/chrome/browser/renderer_host/render_view_host.cc
+++ b/chrome/browser/renderer_host/render_view_host.cc
@@ -1279,11 +1279,6 @@ void RenderViewHost::OnMsgDOMUISend(
return;
}
- // DOMUI doesn't use these values yet.
- // TODO(aa): When DOMUI is ported to ExtensionFunctionDispatcher, send real
- // values here.
- const int kRequestId = -1;
- const bool kHasCallback = false;
scoped_ptr<Value> value;
if (!content.empty()) {
value.reset(base::JSONReader::Read(content, false));
@@ -1295,11 +1290,18 @@ void RenderViewHost::OnMsgDOMUISend(
}
}
- delegate_->ProcessDOMUIMessage(message,
- static_cast<const ListValue*>(value.get()),
- source_url,
- kRequestId,
- kHasCallback);
+ ViewHostMsg_DomMessage_Params params;
+ params.name = message;
+ if (value.get())
+ params.arguments.Swap(static_cast<ListValue*>(value.get()));
+ params.source_url = source_url;
+ // DOMUI doesn't use these values yet.
+ // TODO(aa): When DOMUI is ported to ExtensionFunctionDispatcher, send real
+ // values here.
+ params.request_id = -1;
+ params.has_callback = false;
+ params.user_gesture = false;
+ delegate_->ProcessDOMUIMessage(params);
}
void RenderViewHost::OnMsgForwardMessageToExternalHost(
@@ -1904,21 +1906,17 @@ void RenderViewHost::OnRequestNotificationPermission(
}
}
-void RenderViewHost::OnExtensionRequest(const std::string& name,
- const ListValue& args,
- const GURL& source_url,
- int request_id,
- bool has_callback) {
+void RenderViewHost::OnExtensionRequest(
+ const ViewHostMsg_DomMessage_Params& params) {
if (!ChildProcessSecurityPolicy::GetInstance()->
HasExtensionBindings(process()->id())) {
// This can happen if someone uses window.open() to open an extension URL
// from a non-extension context.
- BlockExtensionRequest(request_id);
+ BlockExtensionRequest(params.request_id);
return;
}
- delegate_->ProcessDOMUIMessage(name, &args, source_url, request_id,
- has_callback);
+ delegate_->ProcessDOMUIMessage(params);
}
void RenderViewHost::SendExtensionResponse(int request_id, bool success,
diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h
index a6d99be..58b8388 100644
--- a/chrome/browser/renderer_host/render_view_host.h
+++ b/chrome/browser/renderer_host/render_view_host.h
@@ -36,6 +36,7 @@ struct ContextMenuParams;
struct MediaPlayerAction;
struct ThumbnailScore;
struct ViewHostMsg_DidPrintPage_Params;
+struct ViewHostMsg_DomMessage_Params;
struct ViewHostMsg_RunFileChooser_Params;
struct ViewHostMsg_ShowNotification_Params;
struct ViewMsg_Navigate_Params;
@@ -636,10 +637,7 @@ class RenderViewHost : public RenderWidgetHost {
void OnCancelDesktopNotification(int notification_id);
void OnRequestNotificationPermission(const GURL& origin, int callback_id);
- void OnExtensionRequest(const std::string& name, const ListValue& args,
- const GURL& source_url,
- int request_id,
- bool has_callback);
+ void OnExtensionRequest(const ViewHostMsg_DomMessage_Params& params);
void OnExtensionPostMessage(int port_id, const std::string& message);
void OnAccessibilityFocusChange(int acc_obj_id);
void OnAccessibilityObjectStateChange(int acc_obj_id);
diff --git a/chrome/browser/renderer_host/render_view_host_delegate.h b/chrome/browser/renderer_host/render_view_host_delegate.h
index 328826f..51e5029 100644
--- a/chrome/browser/renderer_host/render_view_host_delegate.h
+++ b/chrome/browser/renderer_host/render_view_host_delegate.h
@@ -45,6 +45,7 @@ class SSLAddCertHandler;
class TabContents;
struct ThumbnailScore;
struct ViewHostMsg_DidPrintPage_Params;
+struct ViewHostMsg_DomMessage_Params;
struct ViewHostMsg_FrameNavigate_Params;
struct ViewHostMsg_GetSearchProviderInstallState_Params;
struct ViewHostMsg_RunFileChooser_Params;
@@ -716,11 +717,8 @@ class RenderViewHostDelegate {
// A message was sent from HTML-based UI.
// By default we ignore such messages.
- 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) {}
// A message for external host. By default we ignore such messages.
// |receiver| can be a receiving script and |message| is any
diff --git a/chrome/browser/sidebar/sidebar_container.cc b/chrome/browser/sidebar/sidebar_container.cc
new file mode 100644
index 0000000..4c73110
--- /dev/null
+++ b/chrome/browser/sidebar/sidebar_container.cc
@@ -0,0 +1,73 @@
+// 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/sidebar/sidebar_container.h"
+
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/tab_contents/navigation_controller.h"
+#include "chrome/browser/tab_contents/navigation_entry.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/tab_contents/tab_contents_view.h"
+#include "chrome/common/bindings_policy.h"
+#include "googleurl/src/gurl.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+SidebarContainer::SidebarContainer(TabContents* tab,
+ const std::string& content_id,
+ Delegate* delegate)
+ : tab_(tab),
+ content_id_(content_id),
+ delegate_(delegate),
+ icon_(new SkBitmap) {
+ // Create TabContents for sidebar.
+ sidebar_contents_.reset(
+ new TabContents(tab->profile(), NULL, MSG_ROUTING_NONE, NULL));
+ sidebar_contents_->render_view_host()->set_is_extension_process(true);
+ sidebar_contents_->render_view_host()->AllowBindings(
+ BindingsPolicy::EXTENSION);
+ sidebar_contents_->set_delegate(this);
+}
+
+SidebarContainer::~SidebarContainer() {
+}
+
+void SidebarContainer::SidebarClosing() {
+ delegate_->UpdateSidebar(this);
+}
+
+int SidebarContainer::GetTabId() const {
+ return tab_->controller().session_id().id();
+}
+
+void SidebarContainer::Show() {
+ delegate_->UpdateSidebar(this);
+}
+
+void SidebarContainer::Expand() {
+ delegate_->UpdateSidebar(this);
+ sidebar_contents_->view()->SetInitialFocus();
+}
+
+void SidebarContainer::Collapse() {
+ delegate_->UpdateSidebar(this);
+}
+
+void SidebarContainer::Navigate(const GURL& url) {
+ DCHECK(sidebar_contents_.get());
+ // TODO(alekseys): add a progress UI.
+ sidebar_contents_->controller().LoadURL(
+ url, GURL(), PageTransition::START_PAGE);
+}
+
+void SidebarContainer::SetBadgeText(const string16& badge_text) {
+ badge_text_ = badge_text;
+}
+
+void SidebarContainer::SetIcon(const SkBitmap& bitmap) {
+ *icon_ = bitmap;
+}
+
+void SidebarContainer::SetTitle(const string16& title) {
+ title_ = title;
+}
diff --git a/chrome/browser/sidebar/sidebar_container.h b/chrome/browser/sidebar/sidebar_container.h
new file mode 100644
index 0000000..152331d
--- /dev/null
+++ b/chrome/browser/sidebar/sidebar_container.h
@@ -0,0 +1,141 @@
+// 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_SIDEBAR_SIDEBAR_CONTAINER_H_
+#define CHROME_BROWSER_SIDEBAR_SIDEBAR_CONTAINER_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "base/string16.h"
+#include "chrome/browser/tab_contents/tab_contents_delegate.h"
+
+class BrowserWindow;
+class Profile;
+class RenderViewHost;
+class SkBitmap;
+class TabContents;
+
+///////////////////////////////////////////////////////////////////////////////
+// SidebarContainer
+//
+// Stores one particular sidebar state: sidebar's content, its content id,
+// tab it is linked to, mini tab icon, title etc.
+//
+class SidebarContainer
+ : public TabContentsDelegate {
+ public:
+ // Interface to implement to listen for sidebar update notification.
+ class Delegate {
+ public:
+ Delegate() {}
+ virtual ~Delegate() {}
+ virtual void UpdateSidebar(SidebarContainer* host) = 0;
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Delegate);
+ };
+
+ SidebarContainer(TabContents* tab, const std::string& content_id,
+ Delegate* delegate);
+ virtual ~SidebarContainer();
+
+ // Called right before destroying this sidebar.
+ // Does all the necessary cleanup.
+ void SidebarClosing();
+
+ // Returns id of the tab this sidebar is linked to.
+ int GetTabId() const;
+
+ // Returns sidebar's content id.
+ const std::string& content_id() const { return content_id_; }
+
+ // Returns TabContents sidebar is linked to.
+ TabContents* tab_contents() const { return tab_; }
+
+ // Returns sidebar's TabContents.
+ TabContents* sidebar_contents() const { return sidebar_contents_.get(); }
+
+ // Accessor for the badge text.
+ const string16& badge_text() const { return badge_text_; }
+
+ // Accessor for the icon.
+ const SkBitmap& icon() const { return *icon_; }
+
+ // Accessor for the title.
+ const string16& title() const { return title_; }
+
+ // Functions supporting chrome.experimental.sidebar API.
+
+ // Notifies hosting window that this sidebar was expanded.
+ void Show();
+
+ // Notifies hosting window that this sidebar was expanded.
+ void Expand();
+
+ // Notifies hosting window that this sidebar was collapsed.
+ void Collapse();
+
+ // Navigates sidebar contents to the |url|.
+ void Navigate(const GURL& url);
+
+ // Changes sidebar's badge text.
+ void SetBadgeText(const string16& badge_text);
+
+ // Changes sidebar's icon.
+ void SetIcon(const SkBitmap& bitmap);
+
+ // Changes sidebar's title.
+ void SetTitle(const string16& title);
+
+ private:
+ // Overridden from TabContentsDelegate.
+ virtual void OpenURLFromTab(TabContents* source,
+ const GURL& url,
+ const GURL& referrer,
+ WindowOpenDisposition disposition,
+ PageTransition::Type transition) {}
+ virtual void NavigationStateChanged(const TabContents* source,
+ unsigned changed_flags) {}
+ virtual void AddNewContents(TabContents* source,
+ TabContents* new_contents,
+ WindowOpenDisposition disposition,
+ const gfx::Rect& initial_pos,
+ bool user_gesture) {}
+ virtual void ActivateContents(TabContents* contents) {}
+ virtual void LoadingStateChanged(TabContents* source) {}
+ virtual void CloseContents(TabContents* source) {}
+ virtual void MoveContents(TabContents* source, const gfx::Rect& pos) {}
+ virtual bool IsPopup(TabContents* source) { return false; }
+ virtual void URLStarredChanged(TabContents* source, bool starred) {}
+ virtual void UpdateTargetURL(TabContents* source, const GURL& url) {}
+ virtual void ToolbarSizeChanged(TabContents* source, bool is_animating) {}
+
+ // Contents of the tab this sidebar is linked to.
+ TabContents* tab_;
+
+ // Sidebar's content id. There might be more than one sidebar liked to each
+ // particular tab and they are identified by their unique content id.
+ const std::string content_id_;
+
+ // Sidebar update notification listener.
+ Delegate* delegate_;
+
+ // Sidebar contents.
+ scoped_ptr<TabContents> sidebar_contents_;
+
+ // Badge text displayed on the sidebar's mini tab.
+ string16 badge_text_;
+
+ // Icon displayed on the sidebar's mini tab.
+ scoped_ptr<SkBitmap> icon_;
+
+ // Sidebar's title, displayed as a tooltip for sidebar's mini tab.
+ string16 title_;
+
+ DISALLOW_COPY_AND_ASSIGN(SidebarContainer);
+};
+
+#endif // CHROME_BROWSER_SIDEBAR_SIDEBAR_CONTAINER_H_
+
diff --git a/chrome/browser/sidebar/sidebar_manager.cc b/chrome/browser/sidebar/sidebar_manager.cc
new file mode 100644
index 0000000..5ec9e12
--- /dev/null
+++ b/chrome/browser/sidebar/sidebar_manager.cc
@@ -0,0 +1,323 @@
+// 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/sidebar/sidebar_manager.h"
+
+#include <vector>
+
+#include "base/command_line.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/extensions/extension_sidebar_api.h"
+#include "chrome/browser/pref_service.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/sidebar/sidebar_container.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/pref_names.h"
+#include "googleurl/src/gurl.h"
+
+// static
+SidebarManager* SidebarManager::GetInstance() {
+ return g_browser_process->sidebar_manager();
+}
+
+// static
+bool SidebarManager::IsSidebarAllowed() {
+ return CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableExperimentalExtensionApis);
+}
+
+SidebarManager::SidebarManager() {
+}
+
+SidebarContainer* SidebarManager::GetActiveSidebarContainerFor(
+ TabContents* tab) {
+ TabToSidebarHostMap::iterator it = tab_to_sidebar_host_.find(tab);
+ if (it == tab_to_sidebar_host_.end())
+ return NULL;
+ if (it->second.active_content_id.empty())
+ return NULL;
+ ContentIdToSidebarHostMap::iterator host_it =
+ it->second.content_id_to_sidebar_host.find(it->second.active_content_id);
+ DCHECK(host_it != it->second.content_id_to_sidebar_host.end());
+ return host_it->second;
+}
+
+SidebarContainer* SidebarManager::GetSidebarContainerFor(
+ TabContents* tab, const std::string& content_id) {
+ DCHECK(!content_id.empty());
+ TabToSidebarHostMap::iterator it = tab_to_sidebar_host_.find(tab);
+ if (it == tab_to_sidebar_host_.end())
+ return NULL;
+ ContentIdToSidebarHostMap::iterator host_it =
+ it->second.content_id_to_sidebar_host.find(content_id);
+ if (host_it == it->second.content_id_to_sidebar_host.end())
+ return NULL;
+ return host_it->second;
+}
+
+TabContents* SidebarManager::GetSidebarTabContents(
+ TabContents* tab, const std::string& content_id) {
+ DCHECK(!content_id.empty());
+ SidebarContainer* sidebar_host = GetSidebarContainerFor(tab, content_id);
+ if (!sidebar_host)
+ return NULL;
+ return sidebar_host->sidebar_contents();
+}
+
+void SidebarManager::NotifyStateChanges(
+ TabContents* was_active_sidebar_contents,
+ TabContents* active_sidebar_contents) {
+ if (was_active_sidebar_contents == active_sidebar_contents)
+ return;
+
+ SidebarContainer* was_active_host =
+ was_active_sidebar_contents == NULL ? NULL :
+ FindSidebarContainerFor(was_active_sidebar_contents);
+ SidebarContainer* active_host =
+ active_sidebar_contents == NULL ? NULL :
+ FindSidebarContainerFor(active_sidebar_contents);
+
+ if (was_active_host != NULL) {
+ ExtensionSidebarEventRouter::OnStateChanged(
+ was_active_sidebar_contents->profile(),
+ was_active_host->GetTabId(), was_active_host->content_id(),
+ extension_sidebar_constants::kShownState);
+ }
+
+ if (active_host != NULL) {
+ ExtensionSidebarEventRouter::OnStateChanged(
+ active_sidebar_contents->profile(),
+ active_host->GetTabId(), active_host->content_id(),
+ extension_sidebar_constants::kActiveState);
+ }
+}
+
+void SidebarManager::ShowSidebar(TabContents* tab,
+ const std::string& content_id) {
+ DCHECK(!content_id.empty());
+ SidebarContainer* host = GetSidebarContainerFor(tab, content_id);
+ if (!host) {
+ host = new SidebarContainer(tab, content_id, this);
+ RegisterSidebarContainerFor(tab, host);
+ }
+
+ host->Show();
+
+ ExtensionSidebarEventRouter::OnStateChanged(
+ tab->profile(), host->GetTabId(), content_id,
+ extension_sidebar_constants::kShownState);
+}
+
+void SidebarManager::ExpandSidebar(TabContents* tab,
+ const std::string& content_id) {
+ DCHECK(!content_id.empty());
+ TabToSidebarHostMap::iterator it = tab_to_sidebar_host_.find(tab);
+ if (it == tab_to_sidebar_host_.end())
+ return;
+ // If it's already active, bail out.
+ if (it->second.active_content_id == content_id)
+ return;
+
+ SidebarContainer* host = GetSidebarContainerFor(tab, content_id);
+ DCHECK(host);
+ if (!host)
+ return;
+ it->second.active_content_id = content_id;
+
+ host->Expand();
+}
+
+void SidebarManager::CollapseSidebar(TabContents* tab,
+ const std::string& content_id) {
+ DCHECK(!content_id.empty());
+ TabToSidebarHostMap::iterator it = tab_to_sidebar_host_.find(tab);
+ if (it == tab_to_sidebar_host_.end())
+ return;
+ // If it's not the one active now, bail out.
+ if (it->second.active_content_id != content_id)
+ return;
+
+ SidebarContainer* host = GetSidebarContainerFor(tab, content_id);
+ DCHECK(host);
+ if (!host)
+ return;
+ it->second.active_content_id.clear();
+
+ host->Collapse();
+}
+
+void SidebarManager::HideSidebar(TabContents* tab,
+ const std::string& content_id) {
+ DCHECK(!content_id.empty());
+ TabToSidebarHostMap::iterator it = tab_to_sidebar_host_.find(tab);
+ if (it == tab_to_sidebar_host_.end())
+ return;
+ if (it->second.active_content_id == content_id)
+ it->second.active_content_id.clear();
+
+ SidebarContainer* host = GetSidebarContainerFor(tab, content_id);
+ DCHECK(host);
+ int tab_id = host->GetTabId();
+
+ UnregisterSidebarContainerFor(tab, content_id);
+
+ ExtensionSidebarEventRouter::OnStateChanged(
+ tab->profile(), tab_id, content_id,
+ extension_sidebar_constants::kHiddenState);
+}
+
+void SidebarManager::NavigateSidebar(TabContents* tab,
+ const std::string& content_id,
+ const GURL& url) {
+ DCHECK(!content_id.empty());
+ SidebarContainer* host = GetSidebarContainerFor(tab, content_id);
+ if (!host)
+ return;
+
+ host->Navigate(url);
+}
+
+void SidebarManager::SetSidebarBadgeText(
+ TabContents* tab, const std::string& content_id,
+ const string16& badge_text) {
+ SidebarContainer* host = GetSidebarContainerFor(tab, content_id);
+ if (!host)
+ return;
+ host->SetBadgeText(badge_text);
+}
+
+void SidebarManager::SetSidebarIcon(
+ TabContents* tab, const std::string& content_id,
+ const SkBitmap& bitmap) {
+ SidebarContainer* host = GetSidebarContainerFor(tab, content_id);
+ if (!host)
+ return;
+ host->SetIcon(bitmap);
+}
+
+void SidebarManager::SetSidebarTitle(
+ TabContents* tab, const std::string& content_id,
+ const string16& title) {
+ SidebarContainer* host = GetSidebarContainerFor(tab, content_id);
+ if (!host)
+ return;
+ host->SetTitle(title);
+}
+
+SidebarManager::~SidebarManager() {
+ DCHECK(tab_to_sidebar_host_.empty());
+ DCHECK(sidebar_host_to_tab_.empty());
+}
+
+void SidebarManager::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ if (type == NotificationType::TAB_CONTENTS_DESTROYED) {
+ HideAllSidebars(Source<TabContents>(source).ptr());
+ } else {
+ NOTREACHED() << "Got a notification we didn't register for!";
+ }
+}
+
+void SidebarManager::UpdateSidebar(SidebarContainer* host) {
+ NotificationService::current()->Notify(
+ NotificationType::SIDEBAR_CHANGED,
+ Source<SidebarManager>(this),
+ Details<SidebarContainer>(host));
+}
+
+void SidebarManager::HideAllSidebars(TabContents* tab) {
+ TabToSidebarHostMap::iterator tab_it = tab_to_sidebar_host_.find(tab);
+ if (tab_it == tab_to_sidebar_host_.end())
+ return;
+ const ContentIdToSidebarHostMap& hosts =
+ tab_it->second.content_id_to_sidebar_host;
+
+ std::vector<std::string> content_ids;
+ for (ContentIdToSidebarHostMap::const_iterator it = hosts.begin();
+ it != hosts.end(); ++it) {
+ content_ids.push_back(it->first);
+ }
+
+ for (std::vector<std::string>::iterator it = content_ids.begin();
+ it != content_ids.end(); ++it) {
+ HideSidebar(tab, *it);
+ }
+}
+
+SidebarContainer* SidebarManager::FindSidebarContainerFor(
+ TabContents* sidebar_contents) {
+ for (SidebarHostToTabMap::iterator it = sidebar_host_to_tab_.begin();
+ it != sidebar_host_to_tab_.end();
+ ++it) {
+ if (sidebar_contents == it->first->sidebar_contents())
+ return it->first;
+ }
+ return NULL;
+}
+
+void SidebarManager::RegisterSidebarContainerFor(
+ TabContents* tab, SidebarContainer* sidebar_host) {
+ DCHECK(!GetSidebarContainerFor(tab, sidebar_host->content_id()));
+
+ // If it's a first sidebar for this tab, register destroy notification.
+ if (tab_to_sidebar_host_.find(tab) == tab_to_sidebar_host_.end()) {
+ registrar_.Add(this,
+ NotificationType::TAB_CONTENTS_DESTROYED,
+ Source<TabContents>(tab));
+ }
+
+ BindSidebarHost(tab, sidebar_host);
+}
+
+void SidebarManager::UnregisterSidebarContainerFor(
+ TabContents* tab, const std::string& content_id) {
+ SidebarContainer* host = GetSidebarContainerFor(tab, content_id);
+ DCHECK(host);
+ if (!host)
+ return;
+
+ UnbindSidebarHost(tab, host);
+
+ // If there's no more sidebars linked to this tab, unsubscribe.
+ if (tab_to_sidebar_host_.find(tab) == tab_to_sidebar_host_.end()) {
+ registrar_.Remove(this,
+ NotificationType::TAB_CONTENTS_DESTROYED,
+ Source<TabContents>(tab));
+ }
+
+ // Issue tab closing event post unbound.
+ host->SidebarClosing();
+ // Destroy sidebar container.
+ delete host;
+}
+
+void SidebarManager::BindSidebarHost(TabContents* tab,
+ SidebarContainer* sidebar_host) {
+ const std::string& content_id = sidebar_host->content_id();
+
+ DCHECK(GetSidebarContainerFor(tab, content_id) == NULL);
+ DCHECK(sidebar_host_to_tab_.find(sidebar_host) ==
+ sidebar_host_to_tab_.end());
+
+ tab_to_sidebar_host_[tab].content_id_to_sidebar_host[content_id] =
+ sidebar_host;
+ sidebar_host_to_tab_[sidebar_host] = tab;
+}
+
+void SidebarManager::UnbindSidebarHost(TabContents* tab,
+ SidebarContainer* sidebar_host) {
+ const std::string& content_id = sidebar_host->content_id();
+
+ DCHECK(GetSidebarContainerFor(tab, content_id) == sidebar_host);
+ DCHECK(sidebar_host_to_tab_.find(sidebar_host)->second == tab);
+ DCHECK(tab_to_sidebar_host_[tab].active_content_id != content_id);
+
+ tab_to_sidebar_host_[tab].content_id_to_sidebar_host.erase(content_id);
+ if (tab_to_sidebar_host_[tab].content_id_to_sidebar_host.empty())
+ tab_to_sidebar_host_.erase(tab);
+ sidebar_host_to_tab_.erase(sidebar_host);
+}
diff --git a/chrome/browser/sidebar/sidebar_manager.h b/chrome/browser/sidebar/sidebar_manager.h
new file mode 100644
index 0000000..4f3231e
--- /dev/null
+++ b/chrome/browser/sidebar/sidebar_manager.h
@@ -0,0 +1,156 @@
+// 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_SIDEBAR_SIDEBAR_MANAGER_H_
+#define CHROME_BROWSER_SIDEBAR_SIDEBAR_MANAGER_H_
+
+#include <map>
+#include <set>
+#include <string>
+
+#include "base/ref_counted.h"
+#include "base/string16.h"
+#include "chrome/browser/sidebar/sidebar_container.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+
+class GURL;
+class PrefService;
+class Profile;
+class SidebarContainer;
+class SkBitmap;
+class TabContents;
+
+///////////////////////////////////////////////////////////////////////////////
+// SidebarManager
+//
+// This class is a singleton that manages SidebarContainer instances and
+// maintains a connection between tabs and sidebars.
+//
+class SidebarManager : public NotificationObserver,
+ public base::RefCounted<SidebarManager>,
+ private SidebarContainer::Delegate {
+ public:
+ // Returns s singleton instance.
+ static SidebarManager* GetInstance();
+
+ // Returns true if sidebar is allowed to be displayed in the browser.
+ static bool IsSidebarAllowed();
+
+ SidebarManager();
+
+ // Returns SidebarContainer registered for |tab| and active or NULL if
+ // there is no alive and active SidebarContainer registered for |tab|.
+ SidebarContainer* GetActiveSidebarContainerFor(TabContents* tab);
+
+ // Returns SidebarContainer registered for |tab| and |content_id| or NULL if
+ // there is no such SidebarContainer registered.
+ SidebarContainer* GetSidebarContainerFor(TabContents* tab,
+ const std::string& content_id);
+
+ // Returns sidebar's TabContents registered for |tab| and |content_id|.
+ TabContents* GetSidebarTabContents(TabContents* tab,
+ const std::string& content_id);
+
+ // Sends sidebar state change notification to extensions.
+ void NotifyStateChanges(TabContents* was_active_sidebar_contents,
+ TabContents* active_sidebar_contents);
+
+ // Functions supporting chrome.experimental.sidebar API.
+
+ // Shows sidebar identified by |tab| and |content_id| (only sidebar's
+ // mini tab is visible).
+ void ShowSidebar(TabContents* tab, const std::string& content_id);
+
+ // Expands sidebar identified by |tab| and |content_id|.
+ void ExpandSidebar(TabContents* tab, const std::string& content_id);
+
+ // Collapses sidebar identified by |tab| and |content_id| (has no effect
+ // if sidebar is not expanded).
+ void CollapseSidebar(TabContents* tab, const std::string& content_id);
+
+ // Hides sidebar identified by |tab| and |content_id| (removes sidebar's
+ // mini tab).
+ void HideSidebar(TabContents* tab, const std::string& content_id);
+
+ // Navigates sidebar identified by |tab| and |content_id| to |url|.
+ void NavigateSidebar(TabContents* tab, const std::string& content_id,
+ const GURL& url);
+
+ // Changes sidebar's badge text (displayed on the mini tab).
+ void SetSidebarBadgeText(TabContents* tab, const std::string& content_id,
+ const string16& badge_text);
+
+ // Changes sidebar's icon (displayed on the mini tab).
+ void SetSidebarIcon(TabContents* tab, const std::string& content_id,
+ const SkBitmap& bitmap);
+
+ // Changes sidebar's title (mini tab's tooltip).
+ void SetSidebarTitle(TabContents* tab, const std::string& content_id,
+ const string16& title);
+
+ private:
+ friend class base::RefCounted<SidebarManager>;
+
+ virtual ~SidebarManager();
+
+ // Overridden from NotificationObserver.
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+ // Overridden from SidebarContainer::Delegate.
+ virtual void UpdateSidebar(SidebarContainer* host);
+
+ // Hides all sidebars registered for |tab|.
+ void HideAllSidebars(TabContents* tab);
+
+ // Returns SidebarContainer corresponding to |sidebar_contents|.
+ SidebarContainer* FindSidebarContainerFor(TabContents* sidebar_contents);
+
+ // Registers new SidebarContainer for |tab|. There must be no
+ // other SidebarContainers registered for the RenderViewHost at the moment.
+ void RegisterSidebarContainerFor(TabContents* tab,
+ SidebarContainer* container);
+
+ // Unregisters SidebarContainer identified by |tab| and |content_id|.
+ void UnregisterSidebarContainerFor(TabContents* tab,
+ const std::string& content_id);
+
+ // Records the link between |tab| and |sidebar_host|.
+ void BindSidebarHost(TabContents* tab, SidebarContainer* sidebar_host);
+
+ // Forgets the link between |tab| and |sidebar_host|.
+ void UnbindSidebarHost(TabContents* tab, SidebarContainer* sidebar_host);
+
+ NotificationRegistrar registrar_;
+
+ // This map stores sidebars linked to a particular tab. Sidebars are
+ // identified by their unique content id (string).
+ typedef std::map<std::string, SidebarContainer*>
+ ContentIdToSidebarHostMap;
+ // These two maps are for tracking dependencies between tabs and
+ // their SidebarContainers.
+ //
+ // SidebarManager start listening to SidebarContainers when they are put
+ // into these maps and removes them when they are closing.
+ typedef struct {
+ // Sidebars linked to this tab.
+ ContentIdToSidebarHostMap content_id_to_sidebar_host;
+ // Content id of the currently active (expanded and visible) sidebar.
+ std::string active_content_id;
+ } SidebarStateForTab;
+ typedef std::map<TabContents*, SidebarStateForTab>
+ TabToSidebarHostMap;
+ TabToSidebarHostMap tab_to_sidebar_host_;
+
+ typedef std::map<SidebarContainer*, TabContents*>
+ SidebarHostToTabMap;
+ SidebarHostToTabMap sidebar_host_to_tab_;
+
+ DISALLOW_COPY_AND_ASSIGN(SidebarManager);
+};
+
+#endif // CHROME_BROWSER_SIDEBAR_SIDEBAR_MANAGER_H_
+
diff --git a/chrome/browser/sidebar/sidebar_test.cc b/chrome/browser/sidebar/sidebar_test.cc
new file mode 100644
index 0000000..a518587
--- /dev/null
+++ b/chrome/browser/sidebar/sidebar_test.cc
@@ -0,0 +1,177 @@
+// 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/browser.h"
+#include "chrome/browser/browser_window.h"
+#include "chrome/browser/sidebar/sidebar_manager.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/views/frame/browser_view.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/test/in_process_browser_test.h"
+#include "chrome/test/ui_test_utils.h"
+#include "net/test/test_server.h"
+
+namespace {
+
+const char kSampleContentId[] = "sample_content_id";
+const char kSimplePage[] = "files/sidebar/simple_page.html";
+
+class SidebarTest : public InProcessBrowserTest {
+ public:
+ SidebarTest() {
+ CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableExperimentalExtensionApis);
+ set_show_window(true);
+ }
+
+ protected:
+ void ShowSidebarForCurrentTab() {
+ ShowSidebar(browser()->GetSelectedTabContents());
+ }
+
+ void ExpandSidebarForCurrentTab() {
+ ExpandSidebar(browser()->GetSelectedTabContents());
+ }
+
+ void CollapseSidebarForCurrentTab() {
+ CollapseSidebar(browser()->GetSelectedTabContents());
+ }
+
+ void HideSidebarForCurrentTab() {
+ HideSidebar(browser()->GetSelectedTabContents());
+ }
+
+ void NavigateSidebarForCurrentTabTo(const std::string& test_page) {
+ net::TestServer* server = test_server();
+ ASSERT_TRUE(server);
+ GURL url = server->GetURL(test_page);
+
+ TabContents* tab = browser()->GetSelectedTabContents();
+
+ SidebarManager* sidebar_manager = SidebarManager::GetInstance();
+
+ sidebar_manager->NavigateSidebar(tab, kSampleContentId, url);
+
+ SidebarContainer* sidebar_container =
+ sidebar_manager->GetSidebarContainerFor(tab, kSampleContentId);
+
+ TabContents* client_contents = sidebar_container->sidebar_contents();
+ ui_test_utils::WaitForNavigation(&client_contents->controller());
+ }
+
+ void ShowSidebar(TabContents* tab) {
+ SidebarManager* sidebar_manager = SidebarManager::GetInstance();
+ sidebar_manager->ShowSidebar(tab, kSampleContentId);
+ }
+
+ void ExpandSidebar(TabContents* tab) {
+ SidebarManager* sidebar_manager = SidebarManager::GetInstance();
+ sidebar_manager->ExpandSidebar(tab, kSampleContentId);
+ if (browser()->GetSelectedTabContents() == tab)
+ EXPECT_GT(browser_view()->GetSidebarWidth(), 0);
+ }
+
+ void CollapseSidebar(TabContents* tab) {
+ SidebarManager* sidebar_manager = SidebarManager::GetInstance();
+ sidebar_manager->CollapseSidebar(tab, kSampleContentId);
+ if (browser()->GetSelectedTabContents() == tab)
+ EXPECT_EQ(0, browser_view()->GetSidebarWidth());
+ }
+
+ void HideSidebar(TabContents* tab) {
+ SidebarManager* sidebar_manager = SidebarManager::GetInstance();
+ sidebar_manager->HideSidebar(tab, kSampleContentId);
+ if (browser()->GetSelectedTabContents() == tab)
+ EXPECT_EQ(0, browser_view()->GetSidebarWidth());
+ }
+
+ TabContents* tab_contents(int i) {
+ return browser()->GetTabContentsAt(i);
+ }
+
+ BrowserView* browser_view() const {
+ return static_cast<BrowserView*>(browser()->window());
+ }
+};
+
+IN_PROC_BROWSER_TEST_F(SidebarTest, OpenClose) {
+ ShowSidebarForCurrentTab();
+
+ ExpandSidebarForCurrentTab();
+ CollapseSidebarForCurrentTab();
+
+ ExpandSidebarForCurrentTab();
+ CollapseSidebarForCurrentTab();
+
+ ExpandSidebarForCurrentTab();
+ CollapseSidebarForCurrentTab();
+
+ HideSidebarForCurrentTab();
+
+ ShowSidebarForCurrentTab();
+
+ ExpandSidebarForCurrentTab();
+ CollapseSidebarForCurrentTab();
+
+ HideSidebarForCurrentTab();
+}
+
+IN_PROC_BROWSER_TEST_F(SidebarTest, SwitchingTabs) {
+ ShowSidebarForCurrentTab();
+ ExpandSidebarForCurrentTab();
+
+ browser()->NewTab();
+
+ // Make sure sidebar is not visbile for the newly opened tab.
+ EXPECT_EQ(0, browser_view()->GetSidebarWidth());
+
+ // Switch back to the first tab.
+ browser()->SelectNumberedTab(0);
+
+ // Make sure it is visible now.
+ EXPECT_GT(browser_view()->GetSidebarWidth(), 0);
+
+ HideSidebarForCurrentTab();
+}
+
+IN_PROC_BROWSER_TEST_F(SidebarTest, SidebarOnInactiveTab) {
+ ShowSidebarForCurrentTab();
+ ExpandSidebarForCurrentTab();
+
+ browser()->NewTab();
+
+ // Hide sidebar on inactive (first) tab.
+ HideSidebar(tab_contents(0));
+
+ // Switch back to the first tab.
+ browser()->SelectNumberedTab(0);
+
+ // Make sure sidebar is not visbile anymore.
+ EXPECT_EQ(0, browser_view()->GetSidebarWidth());
+
+ // Show sidebar on inactive (second) tab.
+ ShowSidebar(tab_contents(1));
+ ExpandSidebar(tab_contents(1));
+ // Make sure sidebar is not visible yet.
+ EXPECT_EQ(0, browser_view()->GetSidebarWidth());
+
+ // Switch back to the second tab.
+ browser()->SelectNumberedTab(1);
+ // Make sure sidebar is visible now.
+ EXPECT_GT(browser_view()->GetSidebarWidth(), 0);
+
+ HideSidebarForCurrentTab();
+}
+
+IN_PROC_BROWSER_TEST_F(SidebarTest, SidebarNavigate) {
+ ShowSidebarForCurrentTab();
+
+ NavigateSidebarForCurrentTabTo(kSimplePage);
+
+ HideSidebarForCurrentTab();
+}
+
+} // namespace
+
diff --git a/chrome/browser/tab_contents/background_contents.cc b/chrome/browser/tab_contents/background_contents.cc
index 0876419..d4a0a19 100644
--- a/chrome/browser/tab_contents/background_contents.cc
+++ b/chrome/browser/tab_contents/background_contents.cc
@@ -154,14 +154,11 @@ WebPreferences BackgroundContents::GetWebkitPrefs() {
false); // is_dom_ui
}
-void BackgroundContents::ProcessDOMUIMessage(const std::string& message,
- const ListValue* content,
- const GURL& source_url,
- int request_id,
- bool has_callback) {
+void BackgroundContents::ProcessDOMUIMessage(
+ const ViewHostMsg_DomMessage_Params& params) {
// TODO(rafaelw): It may make sense for extensions to be able to open
// BackgroundContents to chrome-extension://<id> pages. Consider implementing.
- render_view_host_->BlockExtensionRequest(request_id);
+ render_view_host_->BlockExtensionRequest(params.request_id);
}
void BackgroundContents::CreateNewWindow(
diff --git a/chrome/browser/tab_contents/background_contents.h b/chrome/browser/tab_contents/background_contents.h
index 0fb238f..12d9b02 100644
--- a/chrome/browser/tab_contents/background_contents.h
+++ b/chrome/browser/tab_contents/background_contents.h
@@ -69,11 +69,7 @@ class BackgroundContents : public RenderViewHostDelegate,
virtual void DidNavigate(RenderViewHost* render_view_host,
const ViewHostMsg_FrameNavigate_Params& params);
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/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc
index a0ef815..c8e212f 100644
--- a/chrome/browser/tab_contents/tab_contents.cc
+++ b/chrome/browser/tab_contents/tab_contents.cc
@@ -2585,20 +2585,15 @@ void TabContents::DomOperationResponse(const std::string& json_string,
int automation_id) {
}
-void TabContents::ProcessDOMUIMessage(const std::string& message,
- const ListValue* content,
- const GURL& source_url,
- int request_id,
- bool has_callback) {
+void TabContents::ProcessDOMUIMessage(
+ const ViewHostMsg_DomMessage_Params& params) {
if (!render_manager_.dom_ui()) {
// This can happen if someone uses window.open() to open an extension URL
// from a non-extension context.
- render_view_host()->BlockExtensionRequest(request_id);
+ render_view_host()->BlockExtensionRequest(params.request_id);
return;
}
- render_manager_.dom_ui()->ProcessDOMUIMessage(message, content, source_url,
- request_id,
- has_callback);
+ render_manager_.dom_ui()->ProcessDOMUIMessage(params);
}
void TabContents::ProcessExternalHostMessage(const std::string& message,
diff --git a/chrome/browser/tab_contents/tab_contents.h b/chrome/browser/tab_contents/tab_contents.h
index 49f89e2..41d298a 100644
--- a/chrome/browser/tab_contents/tab_contents.h
+++ b/chrome/browser/tab_contents/tab_contents.h
@@ -83,6 +83,7 @@ class TabContentsSSLHelper;
class TabContentsView;
class URLPattern;
struct ThumbnailScore;
+struct ViewHostMsg_DomMessage_Params;
struct ViewHostMsg_FrameNavigate_Params;
struct ViewHostMsg_RunFileChooser_Params;
struct WebPreferences;
@@ -920,11 +921,7 @@ class TabContents : public PageNavigator,
WindowOpenDisposition disposition);
virtual void DomOperationResponse(const std::string& json_string,
int automation_id);
- 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 ProcessExternalHostMessage(const std::string& message,
const std::string& origin,
const std::string& target);
diff --git a/chrome/browser/view_ids.h b/chrome/browser/view_ids.h
index f345b3f..c1e02a1 100644
--- a/chrome/browser/view_ids.h
+++ b/chrome/browser/view_ids.h
@@ -71,6 +71,12 @@ enum ViewID {
// The Download shelf.
VIEW_ID_DOWNLOAD_SHELF,
+ // The Sidebar container.
+ VIEW_ID_SIDE_BAR_CONTAINER,
+
+ // The sidebar split.
+ VIEW_ID_SIDE_BAR_SPLIT,
+
// Used in chrome/browser/gtk/view_id_util_browsertests.cc
// If you add new ids, make sure the above test passes.
VIEW_ID_PREDEFINED_COUNT
diff --git a/chrome/browser/views/dropdown_bar_host.cc b/chrome/browser/views/dropdown_bar_host.cc
index 4878e15..d01459e 100644
--- a/chrome/browser/views/dropdown_bar_host.cc
+++ b/chrome/browser/views/dropdown_bar_host.cc
@@ -276,7 +276,7 @@ void DropdownBarHost::UpdateWindowEdges(const gfx::Rect& new_pos) {
// TODO(brettw) this constant is evil. This is the amount of room we've added
// to the window size, when we set the region, it can change the size.
static const int kAddedWidth = 7;
- int difference = new_pos.right() - kAddedWidth - widget_bounds.width() -
+ int difference = new_pos.right() - kAddedWidth - widget_bounds.right() -
gfx::scrollbar_size() + 1;
if (difference > 0) {
Path::Point exclude[4];
diff --git a/chrome/browser/views/find_bar_host.cc b/chrome/browser/views/find_bar_host.cc
index 26a0db0..21dcf8b 100644
--- a/chrome/browser/views/find_bar_host.cc
+++ b/chrome/browser/views/find_bar_host.cc
@@ -227,8 +227,9 @@ gfx::Rect FindBarHost::GetDialogPosition(gfx::Rect avoid_overlapping_rect) {
// Place the view in the top right corner of the widget boundaries (top left
// for RTL languages).
gfx::Rect view_location;
- int x = base::i18n::IsRTL() ?
- widget_bounds.x() : widget_bounds.width() - prefsize.width();
+ int x = widget_bounds.x();
+ if (!base::i18n::IsRTL())
+ x += widget_bounds.width() - prefsize.width();
int y = widget_bounds.y();
view_location.SetRect(x, y, prefsize.width(), prefsize.height());
diff --git a/chrome/browser/views/frame/browser_view.cc b/chrome/browser/views/frame/browser_view.cc
index 1e32b5c..16dd49a 100644
--- a/chrome/browser/views/frame/browser_view.cc
+++ b/chrome/browser/views/frame/browser_view.cc
@@ -32,6 +32,8 @@
#include "chrome/browser/pref_service.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/sessions/tab_restore_service.h"
+#include "chrome/browser/sidebar/sidebar_container.h"
+#include "chrome/browser/sidebar/sidebar_manager.h"
#include "chrome/browser/tab_contents/match_preview.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/tab_contents/tab_contents_view.h"
@@ -484,6 +486,8 @@ BrowserView::BrowserView(Browser* browser)
tabstrip_(NULL),
toolbar_(NULL),
infobar_container_(NULL),
+ sidebar_container_(NULL),
+ sidebar_split_(NULL),
contents_container_(NULL),
devtools_container_(NULL),
preview_container_(NULL),
@@ -497,6 +501,10 @@ BrowserView::BrowserView(Browser* browser)
#endif
{
browser_->tabstrip_model()->AddObserver(this);
+
+ registrar_.Add(this,
+ NotificationType::SIDEBAR_CHANGED,
+ Source<SidebarManager>(SidebarManager::GetInstance()));
}
BrowserView::~BrowserView() {
@@ -618,6 +626,12 @@ gfx::Rect BrowserView::GetTabStripBounds() const {
return frame_->GetBoundsForTabStrip(tabstrip_);
}
+int BrowserView::GetSidebarWidth() const {
+ if (!sidebar_container_ || !sidebar_container_->IsVisible())
+ return 0;
+ return sidebar_split_->divider_offset();
+}
+
bool BrowserView::IsTabStripVisible() const {
return browser_->SupportsWindowFeature(Browser::FEATURE_TABSTRIP);
}
@@ -951,18 +965,24 @@ void BrowserView::RotatePaneFocus(bool forwards) {
// focusable children it will be automatically skipped.
std::vector<AccessibleToolbarView*> accessible_toolbars;
GetAccessibleToolbars(&accessible_toolbars);
- // Add NULL, which represents the tab contents getting focus
- accessible_toolbars.push_back(NULL);
-
- // Figure out which toolbar (if any) currently has the focus.
- AccessibleToolbarView* current_toolbar = NULL;
+ int toolbars_count = static_cast<int>(accessible_toolbars.size());
+
+ std::vector<views::View*> accessible_views(
+ accessible_toolbars.begin(), accessible_toolbars.end());
+ accessible_views.push_back(GetTabContentsContainerView());
+ if (sidebar_container_ && sidebar_container_->IsVisible())
+ accessible_views.push_back(GetSidebarContainerView());
+ if (devtools_container_->IsVisible())
+ accessible_views.push_back(devtools_container_->GetFocusView());
+ int count = static_cast<int>(accessible_views.size());
+
+ // Figure out which view (if any) currently has the focus.
views::View* focused_view = GetRootView()->GetFocusedView();
int index = -1;
- int count = static_cast<int>(accessible_toolbars.size());
if (focused_view) {
- for (int i = 0; i < count; i++) {
- if (accessible_toolbars[i]->IsParentOf(focused_view)) {
- current_toolbar = accessible_toolbars[i];
+ for (int i = 0; i < count; ++i) {
+ if (accessible_views[i] == focused_view ||
+ accessible_views[i]->IsParentOf(focused_view)) {
index = i;
break;
}
@@ -971,7 +991,7 @@ void BrowserView::RotatePaneFocus(bool forwards) {
// If the focus isn't currently in a toolbar, save the focus so we
// can restore it if the user presses Escape.
- if (focused_view && !current_toolbar)
+ if (focused_view && index >= toolbars_count)
SaveFocusedView();
// Try to focus the next pane; if SetToolbarFocusAndFocusDefault returns
@@ -981,16 +1001,15 @@ void BrowserView::RotatePaneFocus(bool forwards) {
if (forwards)
index = (index + 1) % count;
else
- index = ((index - 1) + count + count) % count;
- AccessibleToolbarView* next_toolbar = accessible_toolbars[index];
+ index = ((index - 1) + count) % count;
- if (next_toolbar) {
- if (next_toolbar->SetToolbarFocusAndFocusDefault(
+ if (index < toolbars_count) {
+ if (accessible_toolbars[index]->SetToolbarFocusAndFocusDefault(
last_focused_view_storage_id_)) {
break;
}
} else {
- GetTabContentsContainerView()->RequestFocus();
+ accessible_views[index]->RequestFocus();
break;
}
}
@@ -1374,6 +1393,12 @@ views::View* BrowserView::GetTabContentsContainerView() const {
return contents_container_->GetFocusView();
}
+views::View* BrowserView::GetSidebarContainerView() const {
+ if (!sidebar_container_)
+ return NULL;
+ return sidebar_container_->GetFocusView();
+}
+
ToolbarView* BrowserView::GetToolbarView() const {
return toolbar_;
}
@@ -1411,6 +1436,13 @@ void BrowserView::Observe(NotificationType type,
break;
}
+ case NotificationType::SIDEBAR_CHANGED:
+ if (Details<SidebarContainer>(details)->tab_contents() ==
+ browser_->GetSelectedTabContents()) {
+ UpdateSidebar();
+ }
+ break;
+
default:
NOTREACHED() << "Got a notification we didn't register for!";
break;
@@ -1430,6 +1462,7 @@ void BrowserView::TabDetachedAt(TabContents* contents, int index) {
// on the selected TabContents when it is removed.
contents_container_->ChangeTabContents(NULL);
infobar_container_->ChangeTabContents(NULL);
+ UpdateSidebarForContents(NULL);
UpdateDevToolsForContents(NULL);
}
}
@@ -1843,18 +1876,42 @@ void BrowserView::Init() {
contents_container_ = new TabContentsContainer;
contents_ = new ContentsContainer(this, contents_container_);
+
+ SkColor bg_color = GetWidget()->GetThemeProvider()->
+ GetColor(BrowserThemeProvider::COLOR_TOOLBAR);
+
+ bool sidebar_allowed = SidebarManager::IsSidebarAllowed();
+ if (sidebar_allowed) {
+ sidebar_container_ = new TabContentsContainer;
+ sidebar_container_->SetID(VIEW_ID_SIDE_BAR_CONTAINER);
+ sidebar_container_->SetVisible(false);
+
+ sidebar_split_ = new views::SingleSplitView(
+ contents_,
+ sidebar_container_,
+ views::SingleSplitView::HORIZONTAL_SPLIT);
+ sidebar_split_->SetID(VIEW_ID_SIDE_BAR_SPLIT);
+ sidebar_split_->
+ SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_SIDE_BAR));
+ sidebar_split_->set_background(
+ views::Background::CreateSolidBackground(bg_color));
+ }
+
devtools_container_ = new TabContentsContainer;
devtools_container_->SetID(VIEW_ID_DEV_TOOLS_DOCKED);
devtools_container_->SetVisible(false);
+
+ views::View* contents_view = contents_;
+ if (sidebar_allowed)
+ contents_view = sidebar_split_;
+
contents_split_ = new views::SingleSplitView(
- contents_,
+ contents_view,
devtools_container_,
views::SingleSplitView::VERTICAL_SPLIT);
contents_split_->SetID(VIEW_ID_CONTENTS_SPLIT);
contents_split_->
SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_WEB_CONTENTS));
- SkColor bg_color = GetWidget()->GetThemeProvider()->
- GetColor(BrowserThemeProvider::COLOR_TOOLBAR);
contents_split_->set_background(
views::Background::CreateSolidBackground(bg_color));
AddChildView(contents_split_);
@@ -1953,6 +2010,67 @@ bool BrowserView::MaybeShowInfoBar(TabContents* contents) {
return true;
}
+void BrowserView::UpdateSidebar() {
+ UpdateSidebarForContents(GetSelectedTabContents());
+ Layout();
+}
+
+void BrowserView::UpdateSidebarForContents(TabContents* tab_contents) {
+ if (!sidebar_container_)
+ return; // Happens when sidebar is not allowed.
+ if (!SidebarManager::GetInstance())
+ return; // Happens only in tests.
+
+ TabContents* sidebar_contents = NULL;
+ if (tab_contents) {
+ SidebarContainer* client_host = SidebarManager::GetInstance()->
+ GetActiveSidebarContainerFor(tab_contents);
+ if (client_host)
+ sidebar_contents = client_host->sidebar_contents();
+ }
+
+ bool visible = NULL != sidebar_contents &&
+ browser_->SupportsWindowFeature(Browser::FEATURE_SIDEBAR);
+
+ bool should_show = visible && !sidebar_container_->IsVisible();
+ bool should_hide = !visible && sidebar_container_->IsVisible();
+
+ // Update sidebar content.
+ TabContents* old_contents = sidebar_container_->tab_contents();
+ sidebar_container_->ChangeTabContents(sidebar_contents);
+ SidebarManager::GetInstance()->
+ NotifyStateChanges(old_contents, sidebar_contents);
+
+ // Update sidebar UI width.
+ if (should_show) {
+ // Restore split offset.
+ int sidebar_width = g_browser_process->local_state()->GetInteger(
+ prefs::kExtensionSidebarWidth);
+ if (sidebar_width < 0) {
+ // Initial load, set to default value.
+ sidebar_width = sidebar_split_->width() / 7;
+ }
+ // Make sure user can see both panes.
+ int min_sidebar_width = sidebar_split_->GetMinimumSize().width();
+ sidebar_width = std::min(sidebar_split_->width() - min_sidebar_width,
+ std::max(min_sidebar_width, sidebar_width));
+
+ sidebar_split_->set_divider_offset(
+ sidebar_split_->width() - sidebar_width);
+
+ sidebar_container_->SetVisible(true);
+ sidebar_split_->Layout();
+ } else if (should_hide) {
+ // Store split offset when hiding sidebar only.
+ g_browser_process->local_state()->SetInteger(
+ prefs::kExtensionSidebarWidth,
+ sidebar_split_->width() - sidebar_split_->divider_offset());
+
+ sidebar_container_->SetVisible(false);
+ sidebar_split_->Layout();
+ }
+}
+
void BrowserView::UpdateDevToolsForContents(TabContents* tab_contents) {
TabContents* devtools_contents =
DevToolsWindow::GetDevToolsContents(tab_contents);
@@ -2343,6 +2461,7 @@ void BrowserView::ProcessTabSelected(TabContents* new_contents,
UpdateUIForContents(new_contents);
if (change_tab_contents)
contents_container_->ChangeTabContents(new_contents);
+ UpdateSidebarForContents(new_contents);
UpdateDevToolsForContents(new_contents);
// TODO(beng): This should be called automatically by ChangeTabContents, but I
diff --git a/chrome/browser/views/frame/browser_view.h b/chrome/browser/views/frame/browser_view.h
index d94726a..a56bbb3 100644
--- a/chrome/browser/views/frame/browser_view.h
+++ b/chrome/browser/views/frame/browser_view.h
@@ -144,6 +144,9 @@ class BrowserView : public BrowserBubbleHost,
// offset of IDR_THEME_TOOLBAR.
gfx::Rect GetTabStripBounds() const;
+ // Returns the width of the currently displayed sidebar or 0.
+ int GetSidebarWidth() const;
+
// Accessor for the TabStrip.
BaseTabStrip* tabstrip() const { return tabstrip_; }
@@ -316,6 +319,7 @@ class BrowserView : public BrowserBubbleHost,
virtual BookmarkBarView* GetBookmarkBarView() const;
virtual LocationBarView* GetLocationBarView() const;
virtual views::View* GetTabContentsContainerView() const;
+ virtual views::View* GetSidebarContainerView() const;
virtual ToolbarView* GetToolbarView() const;
// Overridden from NotificationObserver:
@@ -436,6 +440,12 @@ class BrowserView : public BrowserBubbleHost,
// |contents| can be NULL.
bool MaybeShowInfoBar(TabContents* contents);
+ // Updates sidebar UI according to the current tab and sidebar state.
+ void UpdateSidebar();
+ // Displays active sidebar linked to the |tab_contents| or hides sidebar UI,
+ // if there's no such sidebar.
+ void UpdateSidebarForContents(TabContents* tab_contents);
+
// Updated devtools window for given contents.
void UpdateDevToolsForContents(TabContents* tab_contents);
@@ -499,6 +509,42 @@ class BrowserView : public BrowserBubbleHost,
// The Browser object we are associated with.
scoped_ptr<Browser> browser_;
+ // BrowserView layout (LTR one is pictured here).
+ //
+ // --------------------------------------------------------------------------
+ // | | Tabs (1) |
+ // | |--------------------------------------------------------------|
+ // | | Navigation buttons, menus and the address bar (toolbar_) |
+ // | |--------------------------------------------------------------|
+ // | | All infobars (infobar_container_) |
+ // | |--------------------------------------------------------------|
+ // | | Bookmarks (bookmark_bar_view_) |
+ // | |--------------------------------------------------------------|
+ // | |Page content (contents_) || |
+ // | |--------------------------------------|| Sidebar content |
+ // | || contents_container_ or ||| (sidebar_container_) |
+ // | || preview_container_ ||| |
+ // | || |(3) |
+ // | Tabs (2)|| ||| |
+ // | || ||| |
+ // | || ||| |
+ // | || ||| |
+ // | |--------------------------------------|| |
+ // | |==(4)=========================================================|
+ // | | |
+ // | | |
+ // | | Debugger (devtools_container_) |
+ // | | |
+ // | | |
+ // | |--------------------------------------------------------------|
+ // | | Active downloads (download_shelf_) |
+ // --------------------------------------------------------------------------
+ //
+ // (1) - tabstrip_, default position
+ // (2) - tabstrip_, position when side tabs are enabled
+ // (3) - sidebar_split_
+ // (4) - contents_split_
+
// Tool/Info bars that we are currently showing. Used for layout.
// active_bookmark_bar_ is either NULL, if the bookmark bar isn't showing,
// or is bookmark_bar_view_ if the bookmark bar is showing.
@@ -519,6 +565,12 @@ class BrowserView : public BrowserBubbleHost,
// The InfoBarContainer that contains InfoBars for the current tab.
InfoBarContainer* infobar_container_;
+ // The view that contains sidebar for the current tab.
+ TabContentsContainer* sidebar_container_;
+
+ // Split view containing the contents container and sidebar container.
+ views::SingleSplitView* sidebar_split_;
+
// The view that contains the selected TabContents.
TabContentsContainer* contents_container_;
diff --git a/chrome/browser/views/frame/browser_view_layout.cc b/chrome/browser/views/frame/browser_view_layout.cc
index 7aad8b7..f7d8128 100644
--- a/chrome/browser/views/frame/browser_view_layout.cc
+++ b/chrome/browser/views/frame/browser_view_layout.cc
@@ -6,6 +6,7 @@
#include "chrome/browser/find_bar.h"
#include "chrome/browser/find_bar_controller.h"
+#include "chrome/browser/sidebar/sidebar_manager.h"
#include "chrome/browser/view_ids.h"
#include "chrome/browser/views/bookmark_bar_view.h"
#include "chrome/browser/views/download_shelf_view.h"
@@ -204,9 +205,15 @@ void BrowserViewLayout::Uninstalled(views::View* host) {}
void BrowserViewLayout::ViewAdded(views::View* host, views::View* view) {
switch (view->GetID()) {
- case VIEW_ID_CONTENTS_SPLIT:
- contents_split_ = view;
- contents_container_ = contents_split_->GetChildViewAt(0);
+ case VIEW_ID_CONTENTS_SPLIT: {
+ contents_split_ = view;
+ if (SidebarManager::IsSidebarAllowed()) {
+ views::View* sidebar_split = contents_split_->GetChildViewAt(0);
+ contents_container_ = sidebar_split->GetChildViewAt(0);
+ } else {
+ contents_container_ = contents_split_->GetChildViewAt(0);
+ }
+ }
break;
case VIEW_ID_INFO_BAR_CONTAINER:
infobar_container_ = view;
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 59468ab..6b6dc97 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1398,6 +1398,8 @@
'browser/extensions/extension_proxy_api.h',
'browser/extensions/extension_rlz_module.cc',
'browser/extensions/extension_rlz_module.h',
+ 'browser/extensions/extension_sidebar_api.cc',
+ 'browser/extensions/extension_sidebar_api.h',
'browser/extensions/extension_tabs_module.cc',
'browser/extensions/extension_tabs_module.h',
'browser/extensions/extension_tabs_module_constants.cc',
@@ -2393,6 +2395,10 @@
'browser/shell_integration_mac.mm',
'browser/shell_integration_linux.cc',
'browser/shell_integration_win.cc',
+ 'browser/sidebar/sidebar_container.cc',
+ 'browser/sidebar/sidebar_container.h',
+ 'browser/sidebar/sidebar_manager.cc',
+ 'browser/sidebar/sidebar_manager.h',
'browser/speech/speech_input_dispatcher_host.cc',
'browser/speech/speech_input_dispatcher_host.h',
'browser/speech/speech_input_manager.cc',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 6e9ec0c..5680184 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1720,6 +1720,7 @@
'browser/extensions/extension_proxy_apitest.cc',
'browser/extensions/extension_processes_apitest.cc',
'browser/extensions/extension_rlz_apitest.cc',
+ 'browser/extensions/extension_sidebar_apitest.cc',
'browser/extensions/extension_startup_browsertest.cc',
'browser/extensions/extension_storage_apitest.cc',
'browser/extensions/extension_tabs_apitest.cc',
diff --git a/chrome/common/extensions/api/extension_api.json b/chrome/common/extensions/api/extension_api.json
index 670d72b..5004d84 100644
--- a/chrome/common/extensions/api/extension_api.json
+++ b/chrome/common/extensions/api/extension_api.json
@@ -3476,6 +3476,247 @@
"events": []
},
{
+ "namespace": "experimental.sidebar",
+ "types": [],
+ "functions": [
+ {
+ "name": "hide",
+ "type": "function",
+ "description": "Hides sidebar's mini tab for the specified tab and collapses sidebar if it was in 'active' state (see getState). Has no effect if the sidebar is already hidden.",
+ "parameters": [
+ {
+ "type": "object",
+ "name": "details",
+ "optional": true,
+ "properties": {
+ "tabId": {
+ "type": "integer",
+ "minimum": 0,
+ "optional": true,
+ "description": "Defaults to the selected tab of the <a href='windows.html#current-window'>current window</a>."
+ }
+ }
+ }
+ ]
+ },
+ {
+ "name": "show",
+ "type": "function",
+ "description": "Shows sidebar mini tab (in 'shown' state) for the specified tab. Has no effect if already expanded, otherwise changes status to 'shown'.",
+ "parameters": [
+ {
+ "type": "object",
+ "name": "details",
+ "optional": true,
+ "properties": {
+ "tabId": {
+ "type": "integer",
+ "minimum": 0,
+ "optional": true,
+ "description": "Defaults to the selected tab of the <a href='windows.html#current-window'>current window</a>."
+ }
+ }
+ }
+ ]
+ },
+ {
+ "name": "expand",
+ "type": "function",
+ "description": "Expands sidebar and switches to the specified content (if it was displaying another extension's sidebar content) for the specified tab. Extension is allowed to expand sidebar only in response to an explicit user gesture.",
+ "parameters": [
+ {
+ "type": "object",
+ "name": "details",
+ "optional": true,
+ "properties": {
+ "tabId": {
+ "type": "integer",
+ "minimum": 0,
+ "optional": true,
+ "description": "Defaults to the selected tab of the <a href='windows.html#current-window'>current window</a>."
+ }
+ }
+ }
+ ]
+ },
+ {
+ "name": "collapse",
+ "type": "function",
+ "description": "Collapses sidebar for the specified tab. Has no effect if sidebar is not in its 'active' state (see getState).",
+ "parameters": [
+ {
+ "type": "object",
+ "name": "details",
+ "optional": true,
+ "properties": {
+ "tabId": {
+ "type": "integer",
+ "minimum": 0,
+ "optional": true,
+ "description": "Defaults to the selected tab of the <a href='windows.html#current-window'>current window</a>."
+ }
+ }
+ }
+ ]
+ },
+ {
+ "name": "navigate",
+ "type": "function",
+ "description": "Navigates sidebar for the specified tab to the specified URL.",
+ "parameters": [
+ {
+ "type": "object",
+ "name": "details",
+ "properties": {
+ "tabId": {
+ "type": "integer",
+ "minimum": 0,
+ "optional": true,
+ "description": "Defaults to the selected tab of the <a href='windows.html#current-window'>current window</a>."
+ },
+ "url": { "type": "string" }
+ }
+ }
+ ]
+ },
+ {
+ "name": "getState",
+ "type": "function",
+ "description": "Returns current sidebar state for the specified tab.",
+ "parameters": [
+ {
+ "type": "object",
+ "name": "details",
+ "optional": true,
+ "properties": {
+ "tabId": {
+ "type": "integer",
+ "minimum": 0,
+ "optional": true,
+ "description": "Defaults to the selected tab of the <a href='windows.html#current-window'>current window</a>."
+ }
+ }
+ },
+ {
+ "type": "function",
+ "name": "callback",
+ "parameters": [
+ {
+ "name": "state",
+ "type": "string",
+ "enum": ["hidden", "shown", "active"],
+ "description": "'hidden' indicates sidebar is not defined for the specified tab (show was never called or hide() was called). Nothing is displayed for this sidebar.</br>'shown' means sidebar is defined for the specified tab; mini tab is displayed for this sidebar. Sidebar UI is either collapsed or displaying a content of some other extension's sidebar.</br>'active' indicates that sidebar is defined for the specified tab; sidebar UI is expanded and displaying this sidebar's content."
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "setBadgeText",
+ "type": "function",
+ "description": "Sets sidebar's mini tab badge text for the specified tab.",
+ "parameters": [
+ {
+ "type": "object",
+ "name": "details",
+ "properties": {
+ "tabId": {
+ "type": "integer",
+ "minimum": 0,
+ "optional": true,
+ "description": "Defaults to the selected tab of the <a href='windows.html#current-window'>current window</a>."
+ },
+ "text": {
+ "type": "string",
+ "description": "The sidebar's badge text. The badge is displayed on top of the sidebar's icon on the mini tab. Any number of characters can be passed, but only about four can fit in the space."
+ }
+ }
+ }
+ ]
+ },
+ {
+ "name": "setIcon",
+ "type": "function",
+ "description": "Sets sidebar's mini tab icon for the specified tab.",
+ "parameters": [
+ {
+ "type": "object",
+ "name": "details",
+ "properties": {
+ "tabId": {
+ "type": "integer",
+ "minimum": 0,
+ "optional": true,
+ "description": "Defaults to the selected tab of the <a href='windows.html#current-window'>current window</a>."
+ },
+ "imageData": {
+ "type": "object",
+ "isInstanceOf": "ImageData",
+ "properties": {},
+ "additionalProperties": { "type": "any" },
+ "description": "Pixel data for an image to show on the sidebar's mini tab. Must be an ImageData object (for example, from a <code>canvas</code> element). Only one of the imagePath/imageData parameters all owed. The extension's icon is used by default. The preferred size of the icon is 16x16 pixels, any other size will be scaled to 16x16.",
+ "optional": true
+ },
+ "path": {
+ "type": "string",
+ "optional": true,
+ "description": "Relative path to an image in the extension to show on the sidebar's mini tab. Only one of the imagePath/imageData parameters all owed. The extension's icon is used by default. The preferred size of the icon is 16x16 pixels, any other size will be scaled to 16x16."
+ }
+ }
+ }
+ ]
+ },
+ {
+ "name": "setTitle",
+ "type": "function",
+ "description": "Sets sidebar's mini tab title for the specified tab.",
+ "parameters": [
+ {
+ "type": "object",
+ "name": "details",
+ "properties": {
+ "tabId": {
+ "type": "integer",
+ "minimum": 0,
+ "optional": true,
+ "description": "Defaults to the selected tab of the <a href='windows.html#current-window'>current window</a>."
+ },
+ "title": {
+ "type": "string",
+ "description": "The sidebar's title. It is displayed in a tooltip over the sidebar's mini tab."
+ }
+ }
+ }
+ ]
+ }
+ ],
+ "events": [
+ {
+ "name": "onStateChanged",
+ "perExtensionEvent": true,
+ "unprivileged": true,
+ "type": "function",
+ "description": "Notifies about sidebar state changes.",
+ "parameters": [
+ {
+ "type": "object",
+ "name": "details",
+ "properties": {
+ "tabId": {
+ "type": "integer",
+ "minimum": 0
+ },
+ "state": {
+ "type": "string",
+ "enum": ["hidden", "shown", "active"]
+ }
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
"namespace": "experimental.omnibox",
"types": [
{
diff --git a/chrome/common/extensions/docs/experimental.html b/chrome/common/extensions/docs/experimental.html
index 4da96e8..5d590f8 100644
--- a/chrome/common/extensions/docs/experimental.html
+++ b/chrome/common/extensions/docs/experimental.html
@@ -302,6 +302,7 @@ on the following experimental APIs:
<a href="experimental.omnibox.html">experimental.omnibox</a></li><li>
<a href="experimental.processes.html">experimental.processes</a></li><li>
<a href="experimental.proxy.html">experimental.proxy</a></li><li>
+ <a href="experimental.sidebar.html">experimental.sidebar</a></li>
<a href="experimental.webNavigation.html">experimental.webNavigation</a></li><li>
<a href="experimental.webRequest.html">experimental.webRequest</a></li>
</ul>
diff --git a/chrome/common/extensions/docs/experimental.sidebar.html b/chrome/common/extensions/docs/experimental.sidebar.html
new file mode 100644
index 0000000..2e089b7
--- /dev/null
+++ b/chrome/common/extensions/docs/experimental.sidebar.html
@@ -0,0 +1,2415 @@
+<!DOCTYPE html><!-- This page is a placeholder for generated extensions api doc. Note:
+ 1) The <head> information in this page is significant, should be uniform
+ across api docs and should be edited only with knowledge of the
+ templating mechanism.
+ 3) All <body>.innerHTML is genereated as an rendering step. If viewed in a
+ browser, it will be re-generated from the template, json schema and
+ authored overview content.
+ 4) The <body>.innerHTML is also generated by an offline step so that this
+ page may easily be indexed by search engines.
+--><html xmlns="http://www.w3.org/1999/xhtml"><head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <link href="css/ApiRefStyles.css" rel="stylesheet" type="text/css">
+ <link href="css/print.css" rel="stylesheet" type="text/css" media="print">
+ <script type="text/javascript" src="../../../third_party/jstemplate/jstemplate_compiled.js">
+ </script>
+ <script type="text/javascript" src="js/api_page_generator.js"></script>
+ <script type="text/javascript" src="js/bootstrap.js"></script>
+ <title>chrome.experimental.sidebar - Google Chrome Extensions - Google Code</title></head>
+ <body> <div id="gc-container" class="labs">
+ <div id="devModeWarning">
+ You are viewing extension docs in chrome via the 'file:' scheme: are you expecting to see local changes when you refresh? You'll need run chrome with --allow-file-access-from-files.
+ </div>
+ <!-- SUBTEMPLATES: DO NOT MOVE FROM THIS LOCATION -->
+ <!-- In particular, sub-templates that recurse, must be used by allowing
+ jstemplate to make a copy of the template in this section which
+ are not operated on by way of the jsskip="true" -->
+ <div style="display:none">
+
+ <!-- VALUE -->
+ <div id="valueTemplate">
+ <dt>
+ <var>paramName</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum">enumerated</span>
+ <span id="typeTemplate">
+ <span>
+ <a> Type</a>
+ </span>
+ <span>
+ <span>
+ array of <span><span></span></span>
+ </span>
+ <span>paramType</span>
+ <span></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo">
+ Undocumented.
+ </dd>
+ <dd>
+ Description of this parameter from the json schema.
+ </dd>
+ <dd>
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd>
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div> <!-- /VALUE -->
+
+ </div> <!-- /SUBTEMPLATES -->
+
+ <a id="top"></a>
+ <div id="skipto">
+ <a href="#gc-pagecontent">Skip to page content</a>
+ <a href="#gc-toc">Skip to main navigation</a>
+ </div>
+ <!-- API HEADER -->
+ <table id="header" width="100%" cellspacing="0" border="0">
+ <tbody><tr>
+ <td valign="middle"><a href="http://code.google.com/"><img src="images/code_labs_logo.gif" height="43" width="161" alt="Google Code Labs" style="border:0; margin:0;"></a></td>
+ <td valign="middle" width="100%" style="padding-left:0.6em;">
+ <form action="http://www.google.com/cse" id="cse" style="margin-top:0.5em">
+ <div id="gsc-search-box">
+ <input type="hidden" name="cx" value="002967670403910741006:61_cvzfqtno">
+ <input type="hidden" name="ie" value="UTF-8">
+ <input type="text" name="q" value="" size="55">
+ <input class="gsc-search-button" type="submit" name="sa" value="Search">
+ <br>
+ <span class="greytext">e.g. "page action" or "tabs"</span>
+ </div>
+ </form>
+
+ <script type="text/javascript" src="http://www.google.com/jsapi"></script>
+ <script type="text/javascript">google.load("elements", "1", {packages: "transliteration"});</script>
+ <script type="text/javascript" src="http://www.google.com/coop/cse/t13n?form=cse&amp;t13n_langs=en"></script>
+ <script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse&amp;lang=en"></script>
+ </td>
+ </tr>
+ </tbody></table>
+
+ <div id="codesiteContent" class="">
+
+ <a id="gc-topnav-anchor"></a>
+ <div id="gc-topnav">
+ <h1>Google Chrome Extensions (<a href="http://code.google.com/labs/">Labs</a>)</h1>
+ <ul id="home" class="gc-topnav-tabs">
+ <li id="home_link">
+ <a href="index.html" title="Google Chrome Extensions home page">Home</a>
+ </li>
+ <li id="docs_link">
+ <a href="docs.html" title="Official Google Chrome Extensions documentation">Docs</a>
+ </li>
+ <li id="faq_link">
+ <a href="faq.html" title="Answers to frequently asked questions about Google Chrome Extensions">FAQ</a>
+ </li>
+ <li id="samples_link">
+ <a href="samples.html" title="Sample extensions (with source code)">Samples</a>
+ </li>
+ <li id="group_link">
+ <a href="http://groups.google.com/a/chromium.org/group/chromium-extensions" title="Google Chrome Extensions developer forum">Group</a>
+ </li>
+ </ul>
+ </div> <!-- end gc-topnav -->
+
+ <div class="g-section g-tpl-170">
+ <!-- SIDENAV -->
+ <div class="g-unit g-first" id="gc-toc">
+ <ul>
+ <li><a href="getstarted.html">Getting Started</a></li>
+ <li><a href="overview.html">Overview</a></li>
+ <li><h2><a href="devguide.html">Developer's Guide</a></h2>
+ <ul>
+ <li>Browser UI
+ <ul>
+ <li><a href="browserAction.html">Browser Actions</a></li>
+ <li><a href="contextMenus.html">Context Menus</a></li>
+ <li><a href="notifications.html">Desktop Notifications</a></li>
+ <li><a href="options.html">Options Pages</a></li>
+ <li><a href="override.html">Override Pages</a></li>
+ <li><a href="pageAction.html">Page Actions</a></li>
+ <li><a href="themes.html">Themes</a></li>
+ </ul>
+ </li>
+ <li>Browser Interaction
+ <ul>
+ <li><a href="bookmarks.html">Bookmarks</a></li>
+ <li><a href="cookies.html">Cookies</a></li>
+ <li><a href="events.html">Events</a></li>
+ <li><a href="history.html">History</a></li>
+ <li><a href="tabs.html">Tabs</a></li>
+ <li><a href="windows.html">Windows</a></li>
+ </ul>
+ </li>
+ <li>Implementation
+ <ul>
+ <li><a href="a11y.html">Accessibility</a></li>
+ <li><a href="background_pages.html">Background Pages</a></li>
+ <li><a href="content_scripts.html">Content Scripts</a></li>
+ <li><a href="xhr.html">Cross-Origin XHR</a></li>
+ <li><a href="idle.html">Idle</a></li>
+ <li><a href="i18n.html">Internationalization</a></li>
+ <li><a href="messaging.html">Message Passing</a></li>
+ <li><a href="npapi.html">NPAPI Plugins</a></li>
+ </ul>
+ </li>
+ <li>Finishing
+ <ul>
+ <li><a href="hosting.html">Hosting</a></li>
+ <li><a href="external_extensions.html">Other Deployment Options</a></li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ <li><h2><a href="tutorials.html">Tutorials</a></h2>
+ <ul>
+ <li><a href="tut_debugging.html">Debugging</a></li>
+ <li><a href="tut_analytics.html">Google Analytics</a></li>
+ <li><a href="tut_oauth.html">OAuth</a></li>
+ </ul>
+ </li>
+ <li><h2>Reference</h2>
+ <ul>
+ <li>Formats
+ <ul>
+ <li><a href="manifest.html">Manifest Files</a></li>
+ <li><a href="match_patterns.html">Match Patterns</a></li>
+ <!-- <li>Packages (.crx)</li> -->
+ </ul>
+ </li>
+ <li><a href="api_index.html">chrome.* APIs</a></li>
+ <li><a href="api_other.html">Other APIs</a></li>
+ </ul>
+ </li>
+ <li><h2><a href="samples.html">Samples</a></h2></li>
+ </ul>
+ </div>
+
+ <div class="g-unit" id="gc-pagecontent">
+ <div id="pageTitle">
+ <h1 class="page_title">chrome.experimental.sidebar</h1>
+ </div>
+ <!-- TABLE OF CONTENTS -->
+ <div id="toc">
+ <h2>Contents</h2>
+ <ol>
+ <li style="display: none; ">
+ <a>h2Name</a>
+ <ol>
+ <li>
+ <a>h3Name</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="#apiReference">API reference: chrome.experimental.sidebar</a>
+ <ol>
+ <li style="display: none; ">
+ <a href="#properties">Properties</a>
+ <ol>
+ <li>
+ <a href="#property-anchor">propertyName</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="#methods">Methods</a>
+ <ol>
+ <li>
+ <a href="#method-collapse">collapse</a>
+ </li><li>
+ <a href="#method-expand">expand</a>
+ </li><li>
+ <a href="#method-getState">getState</a>
+ </li><li>
+ <a href="#method-hide">hide</a>
+ </li><li>
+ <a href="#method-navigate">navigate</a>
+ </li><li>
+ <a href="#method-setBadgeText">setBadgeText</a>
+ </li><li>
+ <a href="#method-setIcon">setIcon</a>
+ </li><li>
+ <a href="#method-setTitle">setTitle</a>
+ </li><li>
+ <a href="#method-show">show</a>
+ </li>
+ </ol>
+ </li>
+ <li>
+ <a href="#events">Events</a>
+ <ol>
+ <li>
+ <a href="#event-onStateChanged">onStateChanged</a>
+ </li>
+ </ol>
+ </li>
+ <li style="display: none; ">
+ <a href="#types">Types</a>
+ <ol>
+ <li>
+ <a href="#id-anchor">id</a>
+ </li>
+ </ol>
+ </li>
+ </ol>
+ </li>
+ </ol>
+ </div>
+ <!-- /TABLE OF CONTENTS -->
+
+ <!-- Standard content lead-in for experimental API pages -->
+ <p id="classSummary">
+ For information on how to use experimental APIs, see the <a href="experimental.html">chrome.experimental.* APIs</a> page.
+ </p>
+
+ <!-- STATIC CONTENT PLACEHOLDER -->
+ <div id="static"></div>
+
+ <!-- API PAGE -->
+ <div class="apiPage">
+ <a name="apiReference"></a>
+ <h2>API reference: chrome.experimental.sidebar</h2>
+
+ <!-- PROPERTIES -->
+ <div class="apiGroup" style="display: none; ">
+ <a name="properties"></a>
+ <h3 id="properties">Properties</h3>
+
+ <div>
+ <a></a>
+ <h4>getLastError</h4>
+ <div class="summary">
+ <!-- Note: intentionally longer 80 columns -->
+ <span>chrome.extension</span><span>lastError</span>
+ </div>
+ <div>
+ </div>
+ </div>
+
+ </div> <!-- /apiGroup -->
+
+ <!-- METHODS -->
+ <div class="apiGroup" id="methods">
+ <a name="methods"></a>
+ <h3>Methods</h3>
+
+ <!-- iterates over all functions -->
+ <div class="apiItem">
+ <a name="method-collapse"></a> <!-- method-anchor -->
+ <h4>collapse</h4>
+
+ <div class="summary"><span style="display: none; ">void</span>
+ <!-- Note: intentionally longer 80 columns -->
+ <span>chrome.experimental.sidebar.collapse</span>(<span class="optional"><span style="display: none; ">, </span><span>object</span>
+ <var><span>details</span></var></span>)</div>
+
+ <div class="description">
+ <p class="todo" style="display: none; ">Undocumented.</p>
+ <p>Collapses sidebar for the specified tab. Has no effect if sidebar is not in its 'active' state (see getState).</p>
+
+ <!-- PARAMETERS -->
+ <h4>Parameters</h4>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>details</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>object</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo">
+ Undocumented.
+ </dd>
+ <dd style="display: none; ">
+ Description of this parameter from the json schema.
+ </dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>tabId</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>integer</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>Defaults to the selected tab of the <a href="windows.html#current-window">current window</a>.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div>
+ </dl>
+
+ <!-- RETURNS -->
+ <h4 style="display: none; ">Returns</h4>
+ <dl>
+ <div style="display: none; ">
+ <div>
+ </div>
+ </div>
+ </dl>
+
+ <!-- CALLBACK -->
+ <div style="display: none; ">
+ <div>
+ <h4>Callback function</h4>
+ <p>
+ The callback <em>parameter</em> should specify a function
+ that looks like this:
+ </p>
+ <p>
+ If you specify the <em>callback</em> parameter, it should
+ specify a function that looks like this:
+ </p>
+
+ <!-- Note: intentionally longer 80 columns -->
+ <pre>function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>);</pre>
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </div>
+ </div>
+
+ <!-- MIN_VERSION -->
+ <p style="display: none; ">
+ This function was added in version <b><span></span></b>.
+ If you require this function, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </p>
+ </div> <!-- /description -->
+
+ </div><div class="apiItem">
+ <a name="method-expand"></a> <!-- method-anchor -->
+ <h4>expand</h4>
+
+ <div class="summary"><span style="display: none; ">void</span>
+ <!-- Note: intentionally longer 80 columns -->
+ <span>chrome.experimental.sidebar.expand</span>(<span class="optional"><span style="display: none; ">, </span><span>object</span>
+ <var><span>details</span></var></span>)</div>
+
+ <div class="description">
+ <p class="todo" style="display: none; ">Undocumented.</p>
+ <p>Expands sidebar and switches to the specified content (if it was displaying another extension's sidebar content) for the specified tab. Extension is allowed to expand sidebar only in response to an explicit user gesture.</p>
+
+ <!-- PARAMETERS -->
+ <h4>Parameters</h4>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>details</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>object</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo">
+ Undocumented.
+ </dd>
+ <dd style="display: none; ">
+ Description of this parameter from the json schema.
+ </dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>tabId</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>integer</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>Defaults to the selected tab of the <a href="windows.html#current-window">current window</a>.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div>
+ </dl>
+
+ <!-- RETURNS -->
+ <h4 style="display: none; ">Returns</h4>
+ <dl>
+ <div style="display: none; ">
+ <div>
+ </div>
+ </div>
+ </dl>
+
+ <!-- CALLBACK -->
+ <div style="display: none; ">
+ <div>
+ <h4>Callback function</h4>
+ <p>
+ The callback <em>parameter</em> should specify a function
+ that looks like this:
+ </p>
+ <p>
+ If you specify the <em>callback</em> parameter, it should
+ specify a function that looks like this:
+ </p>
+
+ <!-- Note: intentionally longer 80 columns -->
+ <pre>function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>);</pre>
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </div>
+ </div>
+
+ <!-- MIN_VERSION -->
+ <p style="display: none; ">
+ This function was added in version <b><span></span></b>.
+ If you require this function, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </p>
+ </div> <!-- /description -->
+
+ </div><div class="apiItem">
+ <a name="method-getState"></a> <!-- method-anchor -->
+ <h4>getState</h4>
+
+ <div class="summary"><span style="display: none; ">void</span>
+ <!-- Note: intentionally longer 80 columns -->
+ <span>chrome.experimental.sidebar.getState</span>(<span class="optional"><span style="display: none; ">, </span><span>object</span>
+ <var><span>details</span></var></span><span class="null"><span>, </span><span>function</span>
+ <var><span>callback</span></var></span>)</div>
+
+ <div class="description">
+ <p class="todo" style="display: none; ">Undocumented.</p>
+ <p>Returns current sidebar state for the specified tab.</p>
+
+ <!-- PARAMETERS -->
+ <h4>Parameters</h4>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>details</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>object</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo">
+ Undocumented.
+ </dd>
+ <dd style="display: none; ">
+ Description of this parameter from the json schema.
+ </dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>tabId</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>integer</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>Defaults to the selected tab of the <a href="windows.html#current-window">current window</a>.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div><div>
+ <div>
+ <dt>
+ <var>callback</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>function</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo">
+ Undocumented.
+ </dd>
+ <dd style="display: none; ">
+ Description of this parameter from the json schema.
+ </dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div>
+ </dl>
+
+ <!-- RETURNS -->
+ <h4 style="display: none; ">Returns</h4>
+ <dl>
+ <div style="display: none; ">
+ <div>
+ </div>
+ </div>
+ </dl>
+
+ <!-- CALLBACK -->
+ <div>
+ <div>
+ <h4>Callback function</h4>
+ <p>
+ The callback <em>parameter</em> should specify a function
+ that looks like this:
+ </p>
+ <p style="display: none; ">
+ If you specify the <em>callback</em> parameter, it should
+ specify a function that looks like this:
+ </p>
+
+ <!-- Note: intentionally longer 80 columns -->
+ <pre>function(<span>string state</span>) <span class="subdued">{...}</span>);</pre>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>state</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>string</span>
+ <span>["hidden", "shown", "active"]</span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>'hidden' indicates sidebar is not defined for the specified tab (show was never called or hide() was called). Nothing is displayed for this sidebar.'shown' means sidebar is defined for the specified tab; mini tab is displayed for this sidebar. Sidebar UI is either collapsed or displaying a content of some other extension's sidebar.'active' indicates that sidebar is defined for the specified tab; sidebar UI is expanded and displaying this sidebar's content.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div>
+ </dl>
+ </div>
+ </div>
+
+ <!-- MIN_VERSION -->
+ <p style="display: none; ">
+ This function was added in version <b><span></span></b>.
+ If you require this function, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </p>
+ </div> <!-- /description -->
+
+ </div><div class="apiItem">
+ <a name="method-hide"></a> <!-- method-anchor -->
+ <h4>hide</h4>
+
+ <div class="summary"><span style="display: none; ">void</span>
+ <!-- Note: intentionally longer 80 columns -->
+ <span>chrome.experimental.sidebar.hide</span>(<span class="optional"><span style="display: none; ">, </span><span>object</span>
+ <var><span>details</span></var></span>)</div>
+
+ <div class="description">
+ <p class="todo" style="display: none; ">Undocumented.</p>
+ <p>Hides sidebar's mini tab for the specified tab and collapses sidebar if it was in 'active' state (see getState). Has no effect if the sidebar is already hidden.</p>
+
+ <!-- PARAMETERS -->
+ <h4>Parameters</h4>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>details</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>object</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo">
+ Undocumented.
+ </dd>
+ <dd style="display: none; ">
+ Description of this parameter from the json schema.
+ </dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>tabId</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>integer</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>Defaults to the selected tab of the <a href="windows.html#current-window">current window</a>.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div>
+ </dl>
+
+ <!-- RETURNS -->
+ <h4 style="display: none; ">Returns</h4>
+ <dl>
+ <div style="display: none; ">
+ <div>
+ </div>
+ </div>
+ </dl>
+
+ <!-- CALLBACK -->
+ <div style="display: none; ">
+ <div>
+ <h4>Callback function</h4>
+ <p>
+ The callback <em>parameter</em> should specify a function
+ that looks like this:
+ </p>
+ <p>
+ If you specify the <em>callback</em> parameter, it should
+ specify a function that looks like this:
+ </p>
+
+ <!-- Note: intentionally longer 80 columns -->
+ <pre>function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>);</pre>
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </div>
+ </div>
+
+ <!-- MIN_VERSION -->
+ <p style="display: none; ">
+ This function was added in version <b><span></span></b>.
+ If you require this function, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </p>
+ </div> <!-- /description -->
+
+ </div><div class="apiItem">
+ <a name="method-navigate"></a> <!-- method-anchor -->
+ <h4>navigate</h4>
+
+ <div class="summary"><span style="display: none; ">void</span>
+ <!-- Note: intentionally longer 80 columns -->
+ <span>chrome.experimental.sidebar.navigate</span>(<span class="null"><span style="display: none; ">, </span><span>object</span>
+ <var><span>details</span></var></span>)</div>
+
+ <div class="description">
+ <p class="todo" style="display: none; ">Undocumented.</p>
+ <p>Navigates sidebar for the specified tab to the specified URL.</p>
+
+ <!-- PARAMETERS -->
+ <h4>Parameters</h4>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>details</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>object</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo">
+ Undocumented.
+ </dd>
+ <dd style="display: none; ">
+ Description of this parameter from the json schema.
+ </dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>tabId</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>integer</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>Defaults to the selected tab of the <a href="windows.html#current-window">current window</a>.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div><div>
+ <div>
+ <dt>
+ <var>url</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>string</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo">
+ Undocumented.
+ </dd>
+ <dd style="display: none; ">
+ Description of this parameter from the json schema.
+ </dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div>
+ </dl>
+
+ <!-- RETURNS -->
+ <h4 style="display: none; ">Returns</h4>
+ <dl>
+ <div style="display: none; ">
+ <div>
+ </div>
+ </div>
+ </dl>
+
+ <!-- CALLBACK -->
+ <div style="display: none; ">
+ <div>
+ <h4>Callback function</h4>
+ <p>
+ The callback <em>parameter</em> should specify a function
+ that looks like this:
+ </p>
+ <p>
+ If you specify the <em>callback</em> parameter, it should
+ specify a function that looks like this:
+ </p>
+
+ <!-- Note: intentionally longer 80 columns -->
+ <pre>function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>);</pre>
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </div>
+ </div>
+
+ <!-- MIN_VERSION -->
+ <p style="display: none; ">
+ This function was added in version <b><span></span></b>.
+ If you require this function, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </p>
+ </div> <!-- /description -->
+
+ </div><div class="apiItem">
+ <a name="method-setBadgeText"></a> <!-- method-anchor -->
+ <h4>setBadgeText</h4>
+
+ <div class="summary"><span style="display: none; ">void</span>
+ <!-- Note: intentionally longer 80 columns -->
+ <span>chrome.experimental.sidebar.setBadgeText</span>(<span class="null"><span style="display: none; ">, </span><span>object</span>
+ <var><span>details</span></var></span>)</div>
+
+ <div class="description">
+ <p class="todo" style="display: none; ">Undocumented.</p>
+ <p>Sets sidebar's mini tab badge text for the specified tab.</p>
+
+ <!-- PARAMETERS -->
+ <h4>Parameters</h4>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>details</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>object</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo">
+ Undocumented.
+ </dd>
+ <dd style="display: none; ">
+ Description of this parameter from the json schema.
+ </dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>tabId</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>integer</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>Defaults to the selected tab of the <a href="windows.html#current-window">current window</a>.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div><div>
+ <div>
+ <dt>
+ <var>text</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>string</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>The sidebar's badge text. The badge is displayed on top of the sidebar's icon on the mini tab. Any number of characters can be passed, but only about four can fit in the space.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div>
+ </dl>
+
+ <!-- RETURNS -->
+ <h4 style="display: none; ">Returns</h4>
+ <dl>
+ <div style="display: none; ">
+ <div>
+ </div>
+ </div>
+ </dl>
+
+ <!-- CALLBACK -->
+ <div style="display: none; ">
+ <div>
+ <h4>Callback function</h4>
+ <p>
+ The callback <em>parameter</em> should specify a function
+ that looks like this:
+ </p>
+ <p>
+ If you specify the <em>callback</em> parameter, it should
+ specify a function that looks like this:
+ </p>
+
+ <!-- Note: intentionally longer 80 columns -->
+ <pre>function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>);</pre>
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </div>
+ </div>
+
+ <!-- MIN_VERSION -->
+ <p style="display: none; ">
+ This function was added in version <b><span></span></b>.
+ If you require this function, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </p>
+ </div> <!-- /description -->
+
+ </div><div class="apiItem">
+ <a name="method-setIcon"></a> <!-- method-anchor -->
+ <h4>setIcon</h4>
+
+ <div class="summary"><span style="display: none; ">void</span>
+ <!-- Note: intentionally longer 80 columns -->
+ <span>chrome.experimental.sidebar.setIcon</span>(<span class="null"><span style="display: none; ">, </span><span>object</span>
+ <var><span>details</span></var></span>)</div>
+
+ <div class="description">
+ <p class="todo" style="display: none; ">Undocumented.</p>
+ <p>Sets sidebar's mini tab icon for the specified tab.</p>
+
+ <!-- PARAMETERS -->
+ <h4>Parameters</h4>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>details</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>object</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo">
+ Undocumented.
+ </dd>
+ <dd style="display: none; ">
+ Description of this parameter from the json schema.
+ </dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>tabId</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>integer</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>Defaults to the selected tab of the <a href="windows.html#current-window">current window</a>.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div><div>
+ <div>
+ <dt>
+ <var>imageData</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>ImageData</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>Pixel data for an image to show on the sidebar's mini tab. Must be an ImageData object (for example, from a <code>canvas</code> element). Only one of the imagePath/imageData parameters all owed. The extension's icon is used by default. The preferred size of the icon is 16x16 pixels, any other size will be scaled to 16x16.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd>
+ <dl>
+ <div style="display: none; ">
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div><div>
+ <div>
+ <dt>
+ <var>path</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>string</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>Relative path to an image in the extension to show on the sidebar's mini tab. Only one of the imagePath/imageData parameters all owed. The extension's icon is used by default. The preferred size of the icon is 16x16 pixels, any other size will be scaled to 16x16.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div>
+ </dl>
+
+ <!-- RETURNS -->
+ <h4 style="display: none; ">Returns</h4>
+ <dl>
+ <div style="display: none; ">
+ <div>
+ </div>
+ </div>
+ </dl>
+
+ <!-- CALLBACK -->
+ <div style="display: none; ">
+ <div>
+ <h4>Callback function</h4>
+ <p>
+ The callback <em>parameter</em> should specify a function
+ that looks like this:
+ </p>
+ <p>
+ If you specify the <em>callback</em> parameter, it should
+ specify a function that looks like this:
+ </p>
+
+ <!-- Note: intentionally longer 80 columns -->
+ <pre>function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>);</pre>
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </div>
+ </div>
+
+ <!-- MIN_VERSION -->
+ <p style="display: none; ">
+ This function was added in version <b><span></span></b>.
+ If you require this function, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </p>
+ </div> <!-- /description -->
+
+ </div><div class="apiItem">
+ <a name="method-setTitle"></a> <!-- method-anchor -->
+ <h4>setTitle</h4>
+
+ <div class="summary"><span style="display: none; ">void</span>
+ <!-- Note: intentionally longer 80 columns -->
+ <span>chrome.experimental.sidebar.setTitle</span>(<span class="null"><span style="display: none; ">, </span><span>object</span>
+ <var><span>details</span></var></span>)</div>
+
+ <div class="description">
+ <p class="todo" style="display: none; ">Undocumented.</p>
+ <p>Sets sidebar's mini tab title for the specified tab.</p>
+
+ <!-- PARAMETERS -->
+ <h4>Parameters</h4>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>details</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>object</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo">
+ Undocumented.
+ </dd>
+ <dd style="display: none; ">
+ Description of this parameter from the json schema.
+ </dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>tabId</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>integer</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>Defaults to the selected tab of the <a href="windows.html#current-window">current window</a>.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div><div>
+ <div>
+ <dt>
+ <var>title</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>string</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>The sidebar's title. It is displayed in a tooltip over the sidebar's mini tab.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div>
+ </dl>
+
+ <!-- RETURNS -->
+ <h4 style="display: none; ">Returns</h4>
+ <dl>
+ <div style="display: none; ">
+ <div>
+ </div>
+ </div>
+ </dl>
+
+ <!-- CALLBACK -->
+ <div style="display: none; ">
+ <div>
+ <h4>Callback function</h4>
+ <p>
+ The callback <em>parameter</em> should specify a function
+ that looks like this:
+ </p>
+ <p>
+ If you specify the <em>callback</em> parameter, it should
+ specify a function that looks like this:
+ </p>
+
+ <!-- Note: intentionally longer 80 columns -->
+ <pre>function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>);</pre>
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </div>
+ </div>
+
+ <!-- MIN_VERSION -->
+ <p style="display: none; ">
+ This function was added in version <b><span></span></b>.
+ If you require this function, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </p>
+ </div> <!-- /description -->
+
+ </div><div class="apiItem">
+ <a name="method-show"></a> <!-- method-anchor -->
+ <h4>show</h4>
+
+ <div class="summary"><span style="display: none; ">void</span>
+ <!-- Note: intentionally longer 80 columns -->
+ <span>chrome.experimental.sidebar.show</span>(<span class="optional"><span style="display: none; ">, </span><span>object</span>
+ <var><span>details</span></var></span>)</div>
+
+ <div class="description">
+ <p class="todo" style="display: none; ">Undocumented.</p>
+ <p>Shows sidebar mini tab (in 'shown' state) for the specified tab. Has no effect if already expanded, otherwise changes status to 'shown'.</p>
+
+ <!-- PARAMETERS -->
+ <h4>Parameters</h4>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>details</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>object</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo">
+ Undocumented.
+ </dd>
+ <dd style="display: none; ">
+ Description of this parameter from the json schema.
+ </dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>tabId</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>integer</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>Defaults to the selected tab of the <a href="windows.html#current-window">current window</a>.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div>
+ </dl>
+
+ <!-- RETURNS -->
+ <h4 style="display: none; ">Returns</h4>
+ <dl>
+ <div style="display: none; ">
+ <div>
+ </div>
+ </div>
+ </dl>
+
+ <!-- CALLBACK -->
+ <div style="display: none; ">
+ <div>
+ <h4>Callback function</h4>
+ <p>
+ The callback <em>parameter</em> should specify a function
+ that looks like this:
+ </p>
+ <p>
+ If you specify the <em>callback</em> parameter, it should
+ specify a function that looks like this:
+ </p>
+
+ <!-- Note: intentionally longer 80 columns -->
+ <pre>function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>);</pre>
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </div>
+ </div>
+
+ <!-- MIN_VERSION -->
+ <p style="display: none; ">
+ This function was added in version <b><span></span></b>.
+ If you require this function, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </p>
+ </div> <!-- /description -->
+
+ </div> <!-- /apiItem -->
+
+ </div> <!-- /apiGroup -->
+
+ <!-- EVENTS -->
+ <div class="apiGroup">
+ <a name="events"></a>
+ <h3 id="events">Events</h3>
+
+ <!-- iterates over all events -->
+ <div class="apiItem">
+ <a name="event-onStateChanged"></a>
+ <h4>onStateChanged</h4>
+
+ <div class="summary">
+ <!-- Note: intentionally longer 80 columns -->
+ <span class="subdued">chrome.experimental.sidebar.</span><span>onStateChanged</span><span class="subdued">.addListener</span>(function(<span>object details</span>) <span class="subdued">{...}</span>);
+ </div>
+
+ <div class="description">
+ <p class="todo" style="display: none; ">Undocumented.</p>
+ <p>Notifies about sidebar state changes.</p>
+
+ <!-- PARAMETERS -->
+ <h4>Parameters</h4>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>details</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>object</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo">
+ Undocumented.
+ </dd>
+ <dd style="display: none; ">
+ Description of this parameter from the json schema.
+ </dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd>
+ <dl>
+ <div>
+ <div>
+ <dt>
+ <var>tabId</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>integer</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo">
+ Undocumented.
+ </dd>
+ <dd style="display: none; ">
+ Description of this parameter from the json schema.
+ </dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div><div>
+ <div>
+ <dt>
+ <var>state</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional" style="display: none; ">optional</span>
+ <span class="enum">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>string</span>
+ <span>["hidden", "shown", "active"]</span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo">
+ Undocumented.
+ </dd>
+ <dd style="display: none; ">
+ Description of this parameter from the json schema.
+ </dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div>
+ </dl>
+
+ </div> <!-- /decription -->
+
+ </div> <!-- /apiItem -->
+
+ </div> <!-- /apiGroup -->
+
+ <!-- TYPES -->
+ <div class="apiGroup" style="display: none; ">
+ <a name="types"></a>
+ <h3 id="types">Types</h3>
+
+ <!-- iterates over all types -->
+ <div class="apiItem">
+ <a></a>
+ <h4>type name</h4>
+
+ <div>
+ </div>
+
+ </div> <!-- /apiItem -->
+
+ </div> <!-- /apiGroup -->
+
+ </div> <!-- /apiPage -->
+ </div> <!-- /gc-pagecontent -->
+ </div> <!-- /g-section -->
+ </div> <!-- /codesiteContent -->
+ <div id="gc-footer" --="">
+ <div class="text">
+ <p>
+ Except as otherwise <a href="http://code.google.com/policies.html#restrictions">noted</a>,
+ the content of this page is licensed under the <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons
+ Attribution 3.0 License</a>, and code samples are licensed under the
+ <a rel="license" href="http://code.google.com/google_bsd_license.html">BSD License</a>.
+ </p>
+ <p>
+ ©2010 Google
+ </p>
+
+<!-- begin analytics -->
+<script src="http://www.google-analytics.com/urchin.js" type="text/javascript"></script>
+<script src="http://www.google-analytics.com/ga.js" type="text/javascript"></script>
+
+<script type="text/javascript">
+ // chrome doc tracking
+ try {
+ var engdocs = _gat._getTracker("YT-10763712-2");
+ engdocs._trackPageview();
+ } catch(err) {}
+
+ // code.google.com site-wide tracking
+ try {
+ _uacct="UA-18071-1";
+ _uanchor=1;
+ _uff=0;
+ urchinTracker();
+ }
+ catch(e) {/* urchinTracker not available. */}
+</script>
+<!-- end analytics -->
+ </div>
+ </div> <!-- /gc-footer -->
+ </div> <!-- /gc-container -->
+</body></html>
diff --git a/chrome/common/notification_type.h b/chrome/common/notification_type.h
index 252f70d..94b1fae 100644
--- a/chrome/common/notification_type.h
+++ b/chrome/common/notification_type.h
@@ -1059,6 +1059,11 @@ class NotificationType {
// TokenAvailableDetails object.
TOKEN_AVAILABLE,
+ // Sent when the sidebar state is changed.
+ // The source is a SidebarManager instance, the details are the changed
+ // SidebarContainer object.
+ SIDEBAR_CHANGED,
+
// If a token request failed, one of these is issued per failed request.
// The source is a TokenService on the Profile. The details are a
// TokenRequestFailedDetails object.
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 02f92424..bb06e8a 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -832,6 +832,8 @@ const char kNextExtensionsUpdateCheck[] = "extensions.autoupdate.next_check";
const char kExtensionBlacklistUpdateVersion[] =
"extensions.blacklistupdate.version";
+const char kExtensionSidebarWidth[] = "extensions.sidebar.width";
+
// New Tab Page URLs that should not be shown as most visited thumbnails.
const char kNTPMostVisitedURLsBlacklist[] = "ntp.most_visited_blacklist";
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 18503a0..086d63d 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -310,6 +310,8 @@ extern const char kExtensionInstallDenyList[];
extern const char kExtensionBlacklistUpdateVersion[];
+extern const char kExtensionSidebarWidth[];
+
extern const char kNTPMostVisitedURLsBlacklist[];
extern const char kNTPMostVisitedPinnedURLs[];
extern const char kNTPTipsCache[];
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h
index 1ffee93..8f6c8ad 100644
--- a/chrome/common/render_messages.h
+++ b/chrome/common/render_messages.h
@@ -18,6 +18,7 @@
#include "base/ref_counted.h"
#include "base/shared_memory.h"
#include "base/string16.h"
+#include "base/values.h"
#include "chrome/common/common_param_traits.h"
#include "chrome/common/css_colors.h"
#include "chrome/common/dom_storage_common.h"
@@ -867,6 +868,27 @@ enum ViewHostMsg_EnablePreferredSizeChangedMode_Flags {
kPreferredSizeHeightThisIsSlow = 1 << 1,
};
+// Parameters structure for ViewHostMsg_ExtensionRequest.
+struct ViewHostMsg_DomMessage_Params {
+ // Message name.
+ std::string name;
+
+ // List of message arguments.
+ ListValue arguments;
+
+ // URL of the frame request was sent from.
+ GURL source_url;
+
+ // Unique request id to match requests and responses.
+ int request_id;
+
+ // True if request has a callback specified.
+ bool has_callback;
+
+ // True if request is executed in response to an explicit user gesture.
+ bool user_gesture;
+};
+
namespace IPC {
template <>
@@ -2711,6 +2733,44 @@ struct ParamTraits<ViewMsg_DeviceOrientationUpdated_Params> {
l->append(")");
}
};
+// Traits for ViewHostMsg_DomMessage_Params structure to pack/unpack.
+template <>
+struct ParamTraits<ViewHostMsg_DomMessage_Params> {
+ typedef ViewHostMsg_DomMessage_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.name);
+ WriteParam(m, p.arguments);
+ WriteParam(m, p.source_url);
+ WriteParam(m, p.request_id);
+ WriteParam(m, p.has_callback);
+ WriteParam(m, p.user_gesture);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->name) &&
+ ReadParam(m, iter, &p->arguments) &&
+ ReadParam(m, iter, &p->source_url) &&
+ ReadParam(m, iter, &p->request_id) &&
+ ReadParam(m, iter, &p->has_callback) &&
+ ReadParam(m, iter, &p->user_gesture);
+ }
+ static void Log(const param_type& p, std::string* l) {
+ l->append("(");
+ LogParam(p.name, l);
+ l->append(", ");
+ LogParam(p.arguments, l);
+ l->append(", ");
+ LogParam(p.source_url, l);
+ l->append(", ");
+ LogParam(p.request_id, l);
+ l->append(", ");
+ LogParam(p.has_callback, l);
+ l->append(", ");
+ LogParam(p.user_gesture, l);
+ l->append(")");
+ }
+};
+
} // namespace IPC
#define MESSAGES_INTERNAL_FILE "chrome/common/render_messages_internal.h"
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index c60dd96..5c445c8 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -2007,12 +2007,8 @@ IPC_BEGIN_MESSAGES(ViewHost)
// A renderer sends this message when an extension process starts an API
// request. The browser will always respond with a ViewMsg_ExtensionResponse.
- IPC_MESSAGE_ROUTED5(ViewHostMsg_ExtensionRequest,
- std::string /* name */,
- ListValue /* arguments */,
- GURL /* source_url */,
- int /* callback id */,
- bool /* has_callback */)
+ IPC_MESSAGE_ROUTED1(ViewHostMsg_ExtensionRequest,
+ ViewHostMsg_DomMessage_Params)
// Notify the browser that this renderer added a listener to an event.
IPC_MESSAGE_CONTROL1(ViewHostMsg_ExtensionAddListener,
diff --git a/chrome/renderer/extensions/extension_process_bindings.cc b/chrome/renderer/extensions/extension_process_bindings.cc
index cbc2cd1..ec7e1c0 100644
--- a/chrome/renderer/extensions/extension_process_bindings.cc
+++ b/chrome/renderer/extensions/extension_process_bindings.cc
@@ -259,8 +259,8 @@ class ExtensionImpl : public ExtensionBase {
return v8::FunctionTemplate::New(GetPopupView);
} else if (name->Equals(v8::String::New("GetPopupParentWindow"))) {
return v8::FunctionTemplate::New(GetPopupParentWindow);
- } else if (name->Equals(v8::String::New("SetExtensionActionIcon"))) {
- return v8::FunctionTemplate::New(SetExtensionActionIcon);
+ } else if (name->Equals(v8::String::New("SetIconCommon"))) {
+ return v8::FunctionTemplate::New(SetIconCommon);
} else if (name->Equals(v8::String::New("IsExtensionProcess"))) {
return v8::FunctionTemplate::New(IsExtensionProcess);
}
@@ -416,8 +416,9 @@ class ExtensionImpl : public ExtensionBase {
// Common code for starting an API request to the browser. |value_args|
// contains the request's arguments.
+ // Steals value_args contents for efficiency.
static v8::Handle<v8::Value> StartRequestCommon(
- const v8::Arguments& args, const ListValue& value_args) {
+ const v8::Arguments& args, ListValue* value_args) {
// Get the current RenderView so that we can send a routed IPC message from
// the correct source.
RenderView* renderview = bindings_utils::GetRenderViewForCurrentContext();
@@ -448,8 +449,14 @@ class ExtensionImpl : public ExtensionBase {
GetPendingRequestMap()[request_id].reset(new PendingRequest(
current_context, name));
- renderview->SendExtensionRequest(name, value_args, source_url,
- request_id, has_callback);
+ ViewHostMsg_DomMessage_Params params;
+ params.name = name;
+ params.arguments.Swap(value_args);
+ params.source_url = source_url;
+ params.request_id = request_id;
+ params.has_callback = has_callback;
+ params.user_gesture = webframe->isProcessingUserGesture();
+ renderview->SendExtensionRequest(params);
return v8::Undefined();
}
@@ -469,15 +476,11 @@ class ExtensionImpl : public ExtensionBase {
return v8::Undefined();
}
- return StartRequestCommon(args, static_cast<const ListValue&>(
- *value_args.get()));
+ return StartRequestCommon(args, static_cast<ListValue*>(value_args.get()));
}
- // A special request for setting the extension action icon. This function
- // accepts a canvas ImageData object, so it needs to do extra processing
- // before sending the request to the browser.
- static v8::Handle<v8::Value> SetExtensionActionIcon(
- const v8::Arguments& args) {
+ static bool ConvertImageDataToBitmapValue(
+ const v8::Arguments& args, Value** bitmap_value) {
v8::Local<v8::Object> extension_args = args[1]->ToObject();
v8::Local<v8::Object> details =
extension_args->Get(v8::String::New("0"))->ToObject();
@@ -491,7 +494,7 @@ class ExtensionImpl : public ExtensionBase {
int data_length = data->Get(v8::String::New("length"))->Int32Value();
if (data_length != 4 * width * height) {
NOTREACHED() << "Invalid argument to setIcon. Expecting ImageData.";
- return v8::Undefined();
+ return false;
}
SkBitmap bitmap;
@@ -512,9 +515,25 @@ class ExtensionImpl : public ExtensionBase {
// Construct the Value object.
IPC::Message bitmap_pickle;
IPC::WriteParam(&bitmap_pickle, bitmap);
- Value* bitmap_value = BinaryValue::CreateWithCopiedBuffer(
+ *bitmap_value = BinaryValue::CreateWithCopiedBuffer(
static_cast<const char*>(bitmap_pickle.data()), bitmap_pickle.size());
+ return true;
+ }
+
+ // A special request for setting the extension action icon and the sidebar
+ // mini tab icon. This function accepts a canvas ImageData object, so it needs
+ // to do extra processing before sending the request to the browser.
+ static v8::Handle<v8::Value> SetIconCommon(
+ const v8::Arguments& args) {
+ Value* bitmap_value = NULL;
+ if (!ConvertImageDataToBitmapValue(args, &bitmap_value))
+ return v8::Undefined();
+
+ v8::Local<v8::Object> extension_args = args[1]->ToObject();
+ v8::Local<v8::Object> details =
+ extension_args->Get(v8::String::New("0"))->ToObject();
+
DictionaryValue* dict = new DictionaryValue();
dict->Set("imageData", bitmap_value);
@@ -526,7 +545,7 @@ class ExtensionImpl : public ExtensionBase {
ListValue list_value;
list_value.Append(dict);
- return StartRequestCommon(args, list_value);
+ return StartRequestCommon(args, &list_value);
}
static v8::Handle<v8::Value> GetRenderViewId(const v8::Arguments& args) {
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 8602b5f..d3b8b8b 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -4587,17 +4587,9 @@ void RenderView::OnWindowFrameChanged(const gfx::Rect& window_frame,
}
#endif // OS_MACOSX
-void RenderView::SendExtensionRequest(const std::string& name,
- const ListValue& args,
- const GURL& source_url,
- int request_id,
- bool has_callback) {
- Send(new ViewHostMsg_ExtensionRequest(routing_id_,
- name,
- args,
- source_url,
- request_id,
- has_callback));
+void RenderView::SendExtensionRequest(
+ const ViewHostMsg_DomMessage_Params& params) {
+ Send(new ViewHostMsg_ExtensionRequest(routing_id_, params));
}
void RenderView::OnExtensionResponse(int request_id,
diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h
index 000fc09..fb4aa71 100644
--- a/chrome/renderer/render_view.h
+++ b/chrome/renderer/render_view.h
@@ -241,10 +241,7 @@ class RenderView : public RenderWidget,
// Extensions ----------------------------------------------------------------
- void SendExtensionRequest(const std::string& name, const ListValue& args,
- const GURL& source_url,
- int request_id,
- bool has_callback);
+ void SendExtensionRequest(const ViewHostMsg_DomMessage_Params& params);
void OnExtensionResponse(int request_id, bool success,
const std::string& response,
diff --git a/chrome/renderer/resources/extension_process_bindings.js b/chrome/renderer/resources/extension_process_bindings.js
index f0986f2..fee9b4c 100644
--- a/chrome/renderer/resources/extension_process_bindings.js
+++ b/chrome/renderer/resources/extension_process_bindings.js
@@ -17,7 +17,7 @@ var chrome = chrome || {};
native function GetRenderViewId();
native function GetPopupParentWindow();
native function GetPopupView();
- native function SetExtensionActionIcon();
+ native function SetIconCommon();
native function IsExtensionProcess();
var chromeHidden = GetChromeHidden();
@@ -535,9 +535,8 @@ var chrome = chrome || {};
};
var canvas;
- function setIconCommon(details, name, parameters, actionType) {
- var EXTENSION_ACTION_ICON_SIZE = 19;
-
+ function setIconCommon(details, name, parameters, actionType, iconSize,
+ nativeFunction) {
if ("iconIndex" in details) {
sendRequest(name, [details], parameters);
} else if ("imageData" in details) {
@@ -554,14 +553,14 @@ var chrome = chrome || {};
"The imageData property must contain an ImageData object.");
}
- if (details.imageData.width > EXTENSION_ACTION_ICON_SIZE ||
- details.imageData.height > EXTENSION_ACTION_ICON_SIZE) {
+ if (details.imageData.width > iconSize ||
+ details.imageData.height > iconSize) {
throw new Error(
"The imageData property must contain an ImageData object that " +
- "is no larger than 19 pixels square.");
+ "is no larger than " + iconSize + " pixels square.");
}
- sendCustomRequest(SetExtensionActionIcon, name, [details], parameters);
+ sendCustomRequest(nativeFunction, name, [details], parameters);
} else if ("path" in details) {
var img = new Image();
img.onerror = function() {
@@ -570,10 +569,8 @@ var chrome = chrome || {};
}
img.onload = function() {
var canvas = document.createElement("canvas");
- canvas.width = img.width > EXTENSION_ACTION_ICON_SIZE ?
- EXTENSION_ACTION_ICON_SIZE : img.width;
- canvas.height = img.height > EXTENSION_ACTION_ICON_SIZE ?
- EXTENSION_ACTION_ICON_SIZE : img.height;
+ canvas.width = img.width > iconSize ? iconSize : img.width;
+ canvas.height = img.height > iconSize ? iconSize : img.height;
var canvas_context = canvas.getContext('2d');
canvas_context.clearRect(0, 0, canvas.width, canvas.height);
@@ -581,8 +578,7 @@ var chrome = chrome || {};
delete details.path;
details.imageData = canvas_context.getImageData(0, 0, canvas.width,
canvas.height);
- sendCustomRequest(SetExtensionActionIcon, name, [details],
- parameters);
+ sendCustomRequest(nativeFunction, name, [details], parameters);
}
img.src = details.path;
} else {
@@ -591,16 +587,31 @@ var chrome = chrome || {};
}
}
+ function setExtensionActionIconCommon(details, name, parameters,
+ actionType) {
+ var EXTENSION_ACTION_ICON_SIZE = 19;
+ setIconCommon(details, name, parameters, actionType,
+ EXTENSION_ACTION_ICON_SIZE, SetIconCommon);
+ }
+
apiFunctions["browserAction.setIcon"].handleRequest = function(details) {
- setIconCommon(
+ setExtensionActionIconCommon(
details, this.name, this.definition.parameters, "browser action");
};
apiFunctions["pageAction.setIcon"].handleRequest = function(details) {
- setIconCommon(
+ setExtensionActionIconCommon(
details, this.name, this.definition.parameters, "page action");
};
+ apiFunctions["experimental.sidebar.setIcon"].handleRequest =
+ function(details) {
+ var SIDEBAR_ICON_SIZE = 16;
+ setIconCommon(
+ details, this.name, this.definition.parameters, "sidebar",
+ SIDEBAR_ICON_SIZE, SetIconCommon);
+ };
+
apiFunctions["contextMenus.create"].handleRequest =
function() {
var args = arguments;
diff --git a/chrome/renderer/resources/renderer_extension_bindings.js b/chrome/renderer/resources/renderer_extension_bindings.js
index 62184c6..22f7f48 100644
--- a/chrome/renderer/resources/renderer_extension_bindings.js
+++ b/chrome/renderer/resources/renderer_extension_bindings.js
@@ -262,6 +262,7 @@ var chrome = chrome || {};
"experimental.tts",
"experimental.proxy",
"experimental.rlz",
+ "experimental.sidebar",
"experimental.webNavigation",
"experimental.webRequest",
"history",
diff --git a/chrome/test/data/extensions/api_test/sidebar/manifest.json b/chrome/test/data/extensions/api_test/sidebar/manifest.json
new file mode 100644
index 0000000..4a55643
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/sidebar/manifest.json
@@ -0,0 +1,7 @@
+{
+ "name": "chrome.experimental.sidebar",
+ "version": "0.1",
+ "description": "end-to-end browser test for chrome.experimental.sidebar API",
+ "background_page": "test.html",
+ "permissions": ["tabs", "experimental"]
+}
diff --git a/chrome/test/data/extensions/api_test/sidebar/simple_page.html b/chrome/test/data/extensions/api_test/sidebar/simple_page.html
new file mode 100644
index 0000000..f8b6c17
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/sidebar/simple_page.html
@@ -0,0 +1,6 @@
+<html>
+ <head>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/chrome/test/data/extensions/api_test/sidebar/test.html b/chrome/test/data/extensions/api_test/sidebar/test.html
new file mode 100644
index 0000000..46f4d74
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/sidebar/test.html
@@ -0,0 +1 @@
+<script src="test.js"></script>
diff --git a/chrome/test/data/extensions/api_test/sidebar/test.js b/chrome/test/data/extensions/api_test/sidebar/test.js
new file mode 100644
index 0000000..56f810b
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/sidebar/test.js
@@ -0,0 +1,226 @@
+// 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.
+
+// API test for chrome.experimental.sidebar.
+// browser_tests.exe --gtest_filter=SidebarApiTest.Sidebar
+
+const assertEq = chrome.test.assertEq;
+const assertTrue = chrome.test.assertTrue;
+const pass = chrome.test.callbackPass;
+
+if (!chrome.sidebar) {
+ chrome.sidebar = chrome.experimental.sidebar;
+}
+
+/**
+* A helper function to show sidebar. Verifies that sidebar was hidden before
+* and is shown after the call.
+* @param {id} tab id to expand sidebar for.
+* @param {function} callback Closure.
+*/
+function showSidebar(id, callback) {
+ chrome.sidebar.getState({tabId: id}, function(state) {
+ assertEq('hidden', state);
+ chrome.sidebar.show({tabId: id});
+ chrome.sidebar.getState({tabId: id}, function(state) {
+ assertEq('shown', state);
+ callback();
+ });
+ });
+}
+
+/**
+* A helper function to expand sidebar. Verifies that sidebar was shown
+* before and is expanded after the call (provided the specified tab
+* is currently selected).
+* @param {id} tab id to expand sidebar for.
+* @param {function} callback Closure.
+*/
+function expandSidebar(id, callback) {
+ chrome.sidebar.getState({tabId: id}, function(state) {
+ assertEq('shown', state);
+ chrome.sidebar.expand({tabId: id});
+ chrome.sidebar.getState({tabId: id}, function(state) {
+ if (undefined == id) {
+ assertEq('active', state);
+ callback();
+ } else {
+ chrome.tabs.get(id, function(tab) {
+ if (tab.selected) {
+ assertEq('active', state);
+ } else {
+ assertEq('shown', state);
+ }
+ callback();
+ });
+ }
+ });
+ });
+}
+
+/**
+* A helper function to collapse sidebar. Verifies that sidebar was active
+* before (provided the specified tab is currently selected) and is not active
+* after the call.
+* @param {id} tab id to collapse sidebar for.
+* @param {function} callback Closure.
+*/
+function collapseSidebar(id, callback) {
+ chrome.sidebar.getState({tabId: id}, function(state) {
+ if (undefined == id) {
+ assertEq('active', state);
+ } else {
+ chrome.tabs.get(id, function(tab) {
+ if (tab.selected) {
+ assertEq('active', state);
+ } else {
+ assertEq('shown', state);
+ }
+ });
+ }
+ chrome.sidebar.collapse({tabId: id});
+ chrome.sidebar.getState({tabId: id}, function(state) {
+ assertEq('shown', state);
+ callback();
+ });
+ });
+}
+
+/**
+* A helper function to hide sidebar. Verifies that sidebar was not hidden
+* before and is hidden after the call.
+* @param {id} tab id to hide sidebar for.
+* @param {function} callback Closure.
+*/
+function hideSidebar(id, callback) {
+ chrome.sidebar.getState({tabId: id}, function(state) {
+ assertTrue('hidden' != state);
+ chrome.sidebar.hide({tabId: id});
+ chrome.sidebar.getState({tabId: id}, function(state) {
+ assertEq('hidden', state);
+ callback();
+ });
+ });
+}
+
+/**
+* A helper function to show sidebar for the current tab.
+* @param {function} callback Closure.
+*/
+function showSidebarForCurrentTab(callback) {
+ showSidebar(undefined, callback);
+}
+
+/**
+* A helper function to expand sidebar for the current tab.
+* @param {function} callback Closure.
+*/
+function expandSidebarForCurrentTab(callback) {
+ expandSidebar(undefined, callback);
+}
+
+/**
+* A helper function to collapse sidebar for the current tab.
+* @param {function} callback Closure.
+*/
+function collapseSidebarForCurrentTab(callback) {
+ collapseSidebar(undefined, callback);
+}
+
+/**
+* A helper function to hide sidebar for the current tab.
+* @param {function} callback Closure.
+*/
+function hideSidebarForCurrentTab(callback) {
+ hideSidebar(undefined, callback);
+}
+
+var tests = [
+ function showHideSidebar() {
+ showSidebarForCurrentTab(function() {
+ expandSidebarForCurrentTab(function() {
+ collapseSidebarForCurrentTab(function() {
+ hideSidebarForCurrentTab(function() {
+ showSidebarForCurrentTab(function() {
+ hideSidebarForCurrentTab(pass());
+ });
+ });
+ });
+ });
+ });
+ },
+
+ function switchingTabs() {
+ showSidebarForCurrentTab(function() {
+ expandSidebarForCurrentTab(function() {
+ chrome.tabs.getSelected(null, function(tabWithSidebar) {
+ chrome.tabs.create({}, function(tab) {
+ // Make sure sidebar is not visible on this new tab.
+ chrome.sidebar.getState({}, function(state) {
+ assertEq('hidden', state);
+ // Switch back to the tab with the sidebar.
+ chrome.tabs.update(tabWithSidebar.id, {selected: true},
+ function(theSameTab) {
+ // It makes sure sidebar is visible before hiding it.
+ hideSidebarForCurrentTab(pass());
+ });
+ });
+ });
+ });
+ });
+ });
+ },
+
+ function sidebarOnInactiveTab() {
+ // 'switchingTabs' test created two tabs.
+ chrome.tabs.getAllInWindow(null, function(tabs) {
+ assertEq(2, tabs.length);
+ showSidebar(tabs[1].id, function() {
+ expandSidebar(tabs[1].id, function() {
+ // Make sure sidebar is not visible on the current tab.
+ chrome.sidebar.getState({}, function(state) {
+ assertEq('hidden', state);
+ // Switch to the tab with the sidebar.
+ chrome.tabs.update(tabs[1].id, {selected: true},
+ function() {
+ // Make sure sidebar is visible on the current tab.
+ chrome.sidebar.getState({}, function(state) {
+ assertEq('active', state);
+
+ // Switch to the tab with no sidebar.
+ chrome.tabs.update(tabs[0].id, {selected: true},
+ function() {
+ collapseSidebar(tabs[1].id, function() {
+ hideSidebar(tabs[1].id, pass());
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+ },
+
+ function navigateSidebar() {
+ showSidebarForCurrentTab(function() {
+ expandSidebarForCurrentTab(function() {
+ chrome.sidebar.navigate({url: 'simple_page.html'});
+ hideSidebarForCurrentTab(pass());
+ });
+ });
+ },
+
+ function testSetFunctions() {
+ showSidebarForCurrentTab(function() {
+ // TODO(alekseys): test unicode strings.
+ chrome.sidebar.setBadgeText({text: 'Some random text'});
+ chrome.sidebar.setIcon({path: 'icon.png'});
+ chrome.sidebar.setTitle({title: 'Some random title'});
+ hideSidebarForCurrentTab(pass());
+ });
+ }
+];
+
+chrome.test.runTests(tests);
diff --git a/chrome/test/interactive_ui/interactive_ui_tests.gypi b/chrome/test/interactive_ui/interactive_ui_tests.gypi
index 72c60c7..856e043 100644
--- a/chrome/test/interactive_ui/interactive_ui_tests.gypi
+++ b/chrome/test/interactive_ui/interactive_ui_tests.gypi
@@ -145,6 +145,8 @@
'<(SHARED_INTERMEDIATE_DIR)/webkit/webkit_resources.rc',
'<(DEPTH)/chrome/browser/accessibility_win_browsertest.cc',
+ # TODO: port sidebar.
+ '<(DEPTH)/chrome/browser/sidebar/sidebar_test.cc',
'<(DEPTH)/chrome/browser/views/browser_views_accessibility_browsertest.cc',
],
'conditions': [
diff --git a/chrome/test/testing_browser_process.h b/chrome/test/testing_browser_process.h
index 65f6cca..73c10db 100644
--- a/chrome/test/testing_browser_process.h
+++ b/chrome/test/testing_browser_process.h
@@ -87,6 +87,10 @@ class TestingBrowserProcess : public BrowserProcess {
return NULL;
}
+ virtual SidebarManager* sidebar_manager() {
+ return NULL;
+ }
+
virtual TabCloseableStateWatcher* tab_closeable_state_watcher() {
return NULL;
}