diff options
19 files changed, 427 insertions, 16 deletions
diff --git a/chrome/browser/extensions/browser_action_apitest.cc b/chrome/browser/extensions/browser_action_apitest.cc index 10f5b01..eafa655 100644 --- a/chrome/browser/extensions/browser_action_apitest.cc +++ b/chrome/browser/extensions/browser_action_apitest.cc @@ -172,3 +172,92 @@ IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, BrowserActionPopup) { EXPECT_EQ(maxSize, bounds.size()); EXPECT_TRUE(GetBrowserActionsBar().HidePopup()); } + +// Test that calling chrome.browserAction.setPopup() can enable and change +// a popup. +IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, BrowserActionAddPopup) { + ASSERT_TRUE(RunExtensionTest("browser_action/add_popup")) << message_; + Extension* extension = GetSingleLoadedExtension(); + ASSERT_TRUE(extension) << message_; + + int tab_id = ExtensionTabUtil::GetTabId(browser()->GetSelectedTabContents()); + + ExtensionAction* browser_action = extension->browser_action(); + ASSERT_TRUE(browser_action) + << "Browser action test extension should have a browser action."; + + ASSERT_FALSE(browser_action->HasPopup(tab_id)); + ASSERT_FALSE(browser_action->HasPopup(ExtensionAction::kDefaultTabId)); + + // Simulate a click on the browser action icon. The onClicked handler + // will add a popup. + { + ResultCatcher catcher; + GetBrowserActionsBar().Press(0); + ASSERT_TRUE(catcher.GetNextResult()); + } + + // The call to setPopup in background.html set a tab id, so the + // current tab's setting should have changed, but the default setting + // should not have changed. + ASSERT_TRUE(browser_action->HasPopup(tab_id)) + << "Clicking on the browser action should have caused a popup to " + << "be added."; + ASSERT_FALSE(browser_action->HasPopup(ExtensionAction::kDefaultTabId)) + << "Clicking on the browser action should not have set a default " + << "popup."; + + ASSERT_STREQ("/a_popup.html", + browser_action->GetPopupUrl(tab_id).path().c_str()); + + // Now change the popup from a_popup.html to another_popup.html by loading + // a page which removes the popup using chrome.browserAction.setPopup(). + { + ResultCatcher catcher; + ui_test_utils::NavigateToURL( + browser(), + GURL(extension->GetResourceURL("change_popup.html"))); + ASSERT_TRUE(catcher.GetNextResult()); + } + + // The call to setPopup in change_popup.html did not use a tab id, + // so the default setting should have changed as well as the current tab. + ASSERT_TRUE(browser_action->HasPopup(tab_id)); + ASSERT_TRUE(browser_action->HasPopup(ExtensionAction::kDefaultTabId)); + ASSERT_STREQ("/another_popup.html", + browser_action->GetPopupUrl(tab_id).path().c_str()); +} + +// Test that calling chrome.browserAction.setPopup() can remove a popup. +IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, BrowserActionRemovePopup) { + // Load the extension, which has a browser action with a default popup. + ASSERT_TRUE(RunExtensionTest("browser_action/remove_popup")) << message_; + Extension* extension = GetSingleLoadedExtension(); + ASSERT_TRUE(extension) << message_; + + int tab_id = ExtensionTabUtil::GetTabId(browser()->GetSelectedTabContents()); + + ExtensionAction* browser_action = extension->browser_action(); + ASSERT_TRUE(browser_action) + << "Browser action test extension should have a browser action."; + + ASSERT_TRUE(browser_action->HasPopup(tab_id)) + << "Expect a browser action popup before the test removes it."; + ASSERT_TRUE(browser_action->HasPopup(ExtensionAction::kDefaultTabId)) + << "Expect a browser action popup is the default for all tabs."; + + // Load a page which removes the popup using chrome.browserAction.setPopup(). + { + ResultCatcher catcher; + ui_test_utils::NavigateToURL( + browser(), + GURL(extension->GetResourceURL("remove_popup.html"))); + ASSERT_TRUE(catcher.GetNextResult()); + } + + ASSERT_FALSE(browser_action->HasPopup(tab_id)) + << "Browser action popup should have been removed."; + ASSERT_TRUE(browser_action->HasPopup(ExtensionAction::kDefaultTabId)) + << "Browser action popup default should not be changed by setting " + << "a specific tab id."; +} diff --git a/chrome/browser/extensions/extension_browser_actions_api.cc b/chrome/browser/extensions/extension_browser_actions_api.cc index 7306d98..c415d02 100644 --- a/chrome/browser/extensions/extension_browser_actions_api.cc +++ b/chrome/browser/extensions/extension_browser_actions_api.cc @@ -61,6 +61,18 @@ bool BrowserActionSetTitleFunction::RunBrowserAction() { return true; } +bool BrowserActionSetPopupFunction::RunBrowserAction() { + std::string popup_string; + EXTENSION_FUNCTION_VALIDATE(details_->GetString(L"popup", &popup_string)); + + GURL popup_url; + if (!popup_string.empty()) + popup_url = dispatcher()->GetExtension()->GetResourceURL(popup_string); + + browser_action_->SetPopupUrl(tab_id_, popup_url); + return true; +} + bool BrowserActionSetBadgeTextFunction::RunBrowserAction() { std::string badge_text; EXTENSION_FUNCTION_VALIDATE(details_->GetString(L"text", &badge_text)); diff --git a/chrome/browser/extensions/extension_browser_actions_api.h b/chrome/browser/extensions/extension_browser_actions_api.h index 524e3b0..742eecd 100644 --- a/chrome/browser/extensions/extension_browser_actions_api.h +++ b/chrome/browser/extensions/extension_browser_actions_api.h @@ -10,6 +10,7 @@ class ExtensionAction; +// Base class for chrome.browserAction.* APIs. class BrowserActionFunction : public SyncExtensionFunction { protected: BrowserActionFunction() : tab_id_(ExtensionAction::kDefaultTabId) {} @@ -29,24 +30,35 @@ class BrowserActionFunction : public SyncExtensionFunction { ExtensionAction* browser_action_; }; +// Implement chrome.browserAction.setIcon(). class BrowserActionSetIconFunction : public BrowserActionFunction { ~BrowserActionSetIconFunction() {} virtual bool RunBrowserAction(); DECLARE_EXTENSION_FUNCTION_NAME("browserAction.setIcon") }; +// Implement chrome.browserAction.setTitle(). class BrowserActionSetTitleFunction : public BrowserActionFunction { ~BrowserActionSetTitleFunction() {} virtual bool RunBrowserAction(); DECLARE_EXTENSION_FUNCTION_NAME("browserAction.setTitle") }; +// Implement chrome.browserActions.setPopup(). +class BrowserActionSetPopupFunction : public BrowserActionFunction { + ~BrowserActionSetPopupFunction() {} + virtual bool RunBrowserAction(); + DECLARE_EXTENSION_FUNCTION_NAME("browserAction.setPopup") +}; + +// Implement chrome.browserAction.setBadgeText(). class BrowserActionSetBadgeTextFunction : public BrowserActionFunction { ~BrowserActionSetBadgeTextFunction() {} virtual bool RunBrowserAction(); DECLARE_EXTENSION_FUNCTION_NAME("browserAction.setBadgeText") }; +// Implement chrome.browserAction.setBadgeBackgroundColor(). class BrowserActionSetBadgeBackgroundColorFunction : public BrowserActionFunction { ~BrowserActionSetBadgeBackgroundColorFunction() {} diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc index 7ba97ff..d39bd07 100644 --- a/chrome/browser/extensions/extension_function_dispatcher.cc +++ b/chrome/browser/extensions/extension_function_dispatcher.cc @@ -122,6 +122,7 @@ void FactoryRegistry::ResetFunctions() { RegisterFunction<BrowserActionSetTitleFunction>(); RegisterFunction<BrowserActionSetBadgeTextFunction>(); RegisterFunction<BrowserActionSetBadgeBackgroundColorFunction>(); + RegisterFunction<BrowserActionSetPopupFunction>(); // Bookmarks. RegisterFunction<GetBookmarksFunction>(); diff --git a/chrome/common/extensions/api/extension_api.json b/chrome/common/extensions/api/extension_api.json index 7f82edf4..75f8b9ca 100755 --- a/chrome/common/extensions/api/extension_api.json +++ b/chrome/common/extensions/api/extension_api.json @@ -1201,7 +1201,7 @@ { "name": "onClicked", "type": "function", - "description": "Fired when a page action icon is clicked if the page action doesn't show a popup.", + "description": "Fired when a page action icon is clicked. This event will not fire if the page action has a popup.", "parameters": [ { "name": "tab", @@ -1269,6 +1269,29 @@ ] }, { + "name": "setPopup", + "type": "function", + "description": "Sets the html document to be opened as a popup when the user clicks on the browser action's icon.", + "parameters": [ + { + "name": "details", + "type": "object", + "properties": { + "tabId": { + "type": "integer", + "optional": true, + "minimum": 0, + "description": "Limits the change to when a particular tab is selected. Automatically resets when the tab is closed." + }, + "popup": { + "type": "string", + "description": "The html file to show in a popup. If set to the empty string (''), no popup is shown." + } + } + } + ] + }, + { "name": "setBadgeText", "type": "function", "description": "Sets the badge text for the browser action. The badge is displayed on top of the icon.", @@ -1324,7 +1347,7 @@ { "name": "onClicked", "type": "function", - "description": "Fired when a browser action icon is clicked.", + "description": "Fired when a browser action icon is clicked. This event will not fire if the browser action has a popup.", "parameters": [ { "name": "tab", diff --git a/chrome/common/extensions/docs/browserAction.html b/chrome/common/extensions/docs/browserAction.html index 800a81e..c46c136 100644 --- a/chrome/common/extensions/docs/browserAction.html +++ b/chrome/common/extensions/docs/browserAction.html @@ -251,6 +251,8 @@ </li><li> <a href="#method-setIcon">setIcon</a> </li><li> + <a href="#method-setPopup">setPopup</a> + </li><li> <a href="#method-setTitle">setTitle</a> </li> </ol> @@ -288,7 +290,7 @@ a browser action can also have a <a href="#tooltip">tooltip</a>, a <a href="#badge">badge</a>, - and a <a href="#popup">popup</a>. + and a <a href="#popups">popup</a>. </p> <p> @@ -323,7 +325,7 @@ like this: <b>"browser_action": { "default_icon": "images/icon19.png", <em>// <b>required</b></em> "default_title": "Google Mail", <em>// optional; shown in tooltip</em> - "popup": "popup.html" <em>// optional</em> + "default_popup": "popup.html" <em>// optional</em> }</b>, ... }</pre> @@ -335,7 +337,7 @@ A browser action must have an <a href="#icon">icon</a>. It can also have a <a href="#tooltip">tooltip</a>, a <a href="#badge">badge</a>, -and a <a href="#popup">popup</a>. +and a <a href="#popups">popup</a>. </p> <h3 id="icon">Icon</h3> @@ -406,9 +408,9 @@ respectively. <p> To add a popup to your browser action, create an HTML file with the popup's contents. -Then specify the HTML file in -the <a href="#manifest">manifest</a>, -using the <b>popup</b> field of <b>browser_action</b>. +Specify the HTML file in the <b>default_popup</b> field of <b>browser_action</b> +in the <a href="#manifest">manifest</a>, or call the +<a href="#method-setPopup">setPopup()</a> method. </p> <a name="H2-6"></a><h2>Tips</h2> @@ -1061,6 +1063,182 @@ For other examples and for help in viewing the source code, see </div> <!-- /description --> </div><div class="apiItem"> + <a name="method-setPopup"></a> <!-- method-anchor --> + <h4>setPopup</h4> + + <div class="summary"><span style="display: none; ">void</span> + <!-- Note: intentionally longer 80 columns --> + <span>chrome.browserAction.setPopup</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 the html document to be opened as a popup when the user clicks on the browser action's icon.</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 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> + </span> + ) + </div> + + </em> + </dt> + <dd class="todo"> + Undocumented. + </dd> + <dd style="display: none; "> + Description of this parameter from the json schema. + </dd> + + <!-- OBJECT PROPERTIES --> + <dd> + <dl> + <div> + <div> + <dt> + <var>tabId</var> + <em> + + <!-- TYPE --> + <div style="display:inline"> + ( + <span class="optional">optional</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> + </span> + ) + </div> + + </em> + </dt> + <dd class="todo" style="display: none; "> + Undocumented. + </dd> + <dd>Limits the change to when a particular tab is selected. Automatically resets when the tab is closed.</dd> + + <!-- OBJECT PROPERTIES --> + <dd style="display: none; "> + <dl> + <div> + <div> + </div> + </div> + </dl> + </dd> + </div> + </div><div> + <div> + <dt> + <var>popup</var> + <em> + + <!-- TYPE --> + <div style="display:inline"> + ( + <span class="optional" style="display: none; ">optional</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> + </span> + ) + </div> + + </em> + </dt> + <dd class="todo" style="display: none; "> + Undocumented. + </dd> + <dd>The html file to show in a popup. If set to the empty string (''), no popup is shown.</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> + + </div> <!-- /description --> + + </div><div class="apiItem"> <a name="method-setTitle"></a> <!-- method-anchor --> <h4>setTitle</h4> @@ -1257,7 +1435,7 @@ For other examples and for help in viewing the source code, see <div class="description"> <p class="todo" style="display: none; ">Undocumented.</p> - <p>Fired when a browser action icon is clicked.</p> + <p>Fired when a browser action icon is clicked. This event will not fire if the browser action has a popup.</p> <!-- PARAMETERS --> <h4>Parameters</h4> diff --git a/chrome/common/extensions/docs/pageAction.html b/chrome/common/extensions/docs/pageAction.html index 5f9f1f6..0b7d9e3 100644 --- a/chrome/common/extensions/docs/pageAction.html +++ b/chrome/common/extensions/docs/pageAction.html @@ -1242,7 +1242,7 @@ For other examples and for help in viewing the source code, see <div class="description"> <p class="todo" style="display: none; ">Undocumented.</p> - <p>Fired when a page action icon is clicked if the page action doesn't show a popup.</p> + <p>Fired when a page action icon is clicked. This event will not fire if the page action has a popup.</p> <!-- PARAMETERS --> <h4>Parameters</h4> diff --git a/chrome/common/extensions/docs/static/browserAction.html b/chrome/common/extensions/docs/static/browserAction.html index aeab32b..224c247 100644 --- a/chrome/common/extensions/docs/static/browserAction.html +++ b/chrome/common/extensions/docs/static/browserAction.html @@ -8,7 +8,7 @@ a browser action can also have a <a href="#tooltip">tooltip</a>, a <a href="#badge">badge</a>, - and a <a href="#popup">popup</a>. + and a <a href="#popups">popup</a>. </p> <p> @@ -44,7 +44,7 @@ like this: <b>"browser_action": { "default_icon": "images/icon19.png", <em>// <b>required</b></em> "default_title": "Google Mail", <em>// optional; shown in tooltip</em> - "popup": "popup.html" <em>// optional</em> + "default_popup": "popup.html" <em>// optional</em> }</b>, ... }</pre> @@ -56,7 +56,7 @@ A browser action must have an <a href="#icon">icon</a>. It can also have a <a href="#tooltip">tooltip</a>, a <a href="#badge">badge</a>, -and a <a href="#popup">popup</a>. +and a <a href="#popups">popup</a>. </p> <h3 id="icon">Icon</h3> @@ -127,9 +127,9 @@ respectively. <p> To add a popup to your browser action, create an HTML file with the popup's contents. -Then specify the HTML file in -the <a href="#manifest">manifest</a>, -using the <b>popup</b> field of <b>browser_action</b>. +Specify the HTML file in the <b>default_popup</b> field of <b>browser_action</b> +in the <a href="#manifest">manifest</a>, or call the +<a href="#method-setPopup">setPopup()</a> method. </p> <h2>Tips</h2> diff --git a/chrome/test/data/extensions/api_test/browser_action/add_popup/a_popup.html b/chrome/test/data/extensions/api_test/browser_action/add_popup/a_popup.html new file mode 100644 index 0000000..7878de9 --- /dev/null +++ b/chrome/test/data/extensions/api_test/browser_action/add_popup/a_popup.html @@ -0,0 +1,6 @@ +<!DOCTYPE html> +<html> + <body> + <div id="test">I am a popup!</div> + </body> +</html> diff --git a/chrome/test/data/extensions/api_test/browser_action/add_popup/another_popup.html b/chrome/test/data/extensions/api_test/browser_action/add_popup/another_popup.html new file mode 100644 index 0000000..e3dfd25 --- /dev/null +++ b/chrome/test/data/extensions/api_test/browser_action/add_popup/another_popup.html @@ -0,0 +1,6 @@ +<!DOCTYPE html> +<html> + <body> + Another popup. + </body> +</html> diff --git a/chrome/test/data/extensions/api_test/browser_action/add_popup/background.html b/chrome/test/data/extensions/api_test/browser_action/add_popup/background.html new file mode 100644 index 0000000..1b513a0 --- /dev/null +++ b/chrome/test/data/extensions/api_test/browser_action/add_popup/background.html @@ -0,0 +1,16 @@ +<!DOCTYPE html> +<html> + <script> + chrome.tabs.getSelected(null, function(tab) { + // When the browser action is clicked, add a popup. + chrome.browserAction.onClicked.addListener(function(tab) { + chrome.browserAction.setPopup({ + tabId: tab.id, + popup: 'a_popup.html' + }); + chrome.test.notifyPass(); + }); + chrome.test.notifyPass(); + }); + </script> +</html> diff --git a/chrome/test/data/extensions/api_test/browser_action/add_popup/change_popup.html b/chrome/test/data/extensions/api_test/browser_action/add_popup/change_popup.html new file mode 100644 index 0000000..877a173 --- /dev/null +++ b/chrome/test/data/extensions/api_test/browser_action/add_popup/change_popup.html @@ -0,0 +1,13 @@ +<!DOCTYPE html> +<html> + <body> + <script> + chrome.tabs.getSelected(null, function(tab) { + chrome.browserAction.setPopup({ + popup: 'another_popup.html' + }); + chrome.test.notifyPass(); + }); + </script> + </body> +</html> diff --git a/chrome/test/data/extensions/api_test/browser_action/add_popup/icon.png b/chrome/test/data/extensions/api_test/browser_action/add_popup/icon.png Binary files differnew file mode 100755 index 0000000..9a79a46 --- /dev/null +++ b/chrome/test/data/extensions/api_test/browser_action/add_popup/icon.png diff --git a/chrome/test/data/extensions/api_test/browser_action/add_popup/manifest.json b/chrome/test/data/extensions/api_test/browser_action/add_popup/manifest.json new file mode 100644 index 0000000..c7ddb6a --- /dev/null +++ b/chrome/test/data/extensions/api_test/browser_action/add_popup/manifest.json @@ -0,0 +1,12 @@ +{ + "name": "A browser action to test chrome.browserAction.setPopup()", + "version": "1.0", + "background_page": "background.html", + "permissions": [ + "tabs", "http://*/*" + ], + "browser_action": { + "default_title": "Test setPopup()", + "default_icon": "icon.png" + } +} diff --git a/chrome/test/data/extensions/api_test/browser_action/remove_popup/a_popup.html b/chrome/test/data/extensions/api_test/browser_action/remove_popup/a_popup.html new file mode 100755 index 0000000..7878de9 --- /dev/null +++ b/chrome/test/data/extensions/api_test/browser_action/remove_popup/a_popup.html @@ -0,0 +1,6 @@ +<!DOCTYPE html> +<html> + <body> + <div id="test">I am a popup!</div> + </body> +</html> diff --git a/chrome/test/data/extensions/api_test/browser_action/remove_popup/background.html b/chrome/test/data/extensions/api_test/browser_action/remove_popup/background.html new file mode 100644 index 0000000..941c81a --- /dev/null +++ b/chrome/test/data/extensions/api_test/browser_action/remove_popup/background.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html> + <body> + <script> + chrome.tabs.getSelected(null, function(tab) { + chrome.test.notifyPass(); + }); + </script> + </body> +</html> diff --git a/chrome/test/data/extensions/api_test/browser_action/remove_popup/icon.png b/chrome/test/data/extensions/api_test/browser_action/remove_popup/icon.png Binary files differnew file mode 100755 index 0000000..9a79a46 --- /dev/null +++ b/chrome/test/data/extensions/api_test/browser_action/remove_popup/icon.png diff --git a/chrome/test/data/extensions/api_test/browser_action/remove_popup/manifest.json b/chrome/test/data/extensions/api_test/browser_action/remove_popup/manifest.json new file mode 100755 index 0000000..3b9b851 --- /dev/null +++ b/chrome/test/data/extensions/api_test/browser_action/remove_popup/manifest.json @@ -0,0 +1,13 @@ +{ + "name": "A page action which removes a popup.", + "version": "1.0", + "background_page": "background.html", + "permissions": [ + "tabs", "http://*/*" + ], + "browser_action": { + "default_title": "Popup Title", + "default_icon": "icon.png", + "default_popup": "a_popup.html" + } +} diff --git a/chrome/test/data/extensions/api_test/browser_action/remove_popup/remove_popup.html b/chrome/test/data/extensions/api_test/browser_action/remove_popup/remove_popup.html new file mode 100644 index 0000000..100b06b --- /dev/null +++ b/chrome/test/data/extensions/api_test/browser_action/remove_popup/remove_popup.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html> + <body> + <script> + chrome.tabs.getSelected(null, function(tab) { + chrome.browserAction.setPopup({ + tabId: tab.id, + popup: '' // No popup. + }); + chrome.test.notifyPass(); + }); + </script> + </body> +</html> |