summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortwiz@chromium.org <twiz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-30 22:39:22 +0000
committertwiz@chromium.org <twiz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-04-30 22:39:22 +0000
commit16e3d45d6fd4a2203ddb248d636dcd320a3639f0 (patch)
treea5b9c90129b896ccaa112e5afc4e390adc8e0571
parentf325f1e12a828a0a3fa74f75e1b2ea8cb49b0102 (diff)
downloadchromium_src-16e3d45d6fd4a2203ddb248d636dcd320a3639f0.zip
chromium_src-16e3d45d6fd4a2203ddb248d636dcd320a3639f0.tar.gz
chromium_src-16e3d45d6fd4a2203ddb248d636dcd320a3639f0.tar.bz2
Clean-up of the asynchronous behaviour of the experimental extension popup API.
- It was previously possible to programmatically launch two popups from the same extension. (Simply call popup.show twice in a row, or in a callback chain.) I removed this incorrect funcationality by registering ExtensionPopupHost to listen for EXTENSION_HOST_CREATED notifications. If a popup is shown, and a new ExtensionHost is constructed of type EXTENSION_POPUP, then the presently displayed popup is dismissed. - The callback function for popup.show(...) was previously called in response to EXTENSION_POPUP_VIEW_READY, as processed in response to a ViewHostMsg_DocumentAvailableInMainFrame message. This message wassent after PARSING of the conent of the popup view. Because of this behaviour, the API was difficult to use because one could not meaningfully interact with the popup page during the callback: The callback would race with completion of the onload handler within the popup, so some sort of polling for onload-complete was required. I fixed the problem by adding new notifications and messages so that EXTENSION_POPUP_VIEW_READY is now sent only after all onload handlers have been invoked.Corresponding unit-tests have also been added. BUG=None TEST=ExtensionApiTest.Popup Review URL: http://codereview.chromium.org/1512007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@46136 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/extensions/extension_host.cc2
-rw-r--r--chrome/browser/extensions/extension_host.h2
-rw-r--r--chrome/browser/extensions/extension_popup_api.cc71
-rw-r--r--chrome/browser/renderer_host/render_view_host.cc6
-rw-r--r--chrome/browser/renderer_host/render_view_host.h1
-rw-r--r--chrome/browser/renderer_host/render_view_host_delegate.h4
-rw-r--r--chrome/common/extensions/api/extension_api.json4
-rw-r--r--chrome/common/extensions/docs/extension.html2
-rw-r--r--chrome/common/extensions/docs/history.html122
-rw-r--r--chrome/common/notification_type.h5
-rw-r--r--chrome/common/render_messages_internal.h4
-rw-r--r--chrome/renderer/extensions/extension_process_bindings.cc2
-rw-r--r--chrome/renderer/render_view.cc3
-rw-r--r--chrome/test/data/extensions/api_test/popup/toolband.html66
-rw-r--r--chrome/test/data/extensions/api_test/popup/toolband_popup_a.html12
-rw-r--r--chrome/test/data/extensions/api_test/popup/toolband_popup_b.html12
16 files changed, 232 insertions, 86 deletions
diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc
index 67af709..4b1b0a4 100644
--- a/chrome/browser/extensions/extension_host.cc
+++ b/chrome/browser/extensions/extension_host.cc
@@ -440,7 +440,9 @@ void ExtensionHost::DocumentAvailableInMainFrame(RenderViewHost* rvh) {
break; // No style sheet for other types, at the moment.
}
}
+}
+void ExtensionHost::DocumentOnLoadCompletedInMainFrame(RenderViewHost* rvh) {
if (ViewType::EXTENSION_POPUP == GetRenderViewType()) {
NotificationService::current()->Notify(
NotificationType::EXTENSION_POPUP_VIEW_READY,
diff --git a/chrome/browser/extensions/extension_host.h b/chrome/browser/extensions/extension_host.h
index 39d2f8b..013cb99 100644
--- a/chrome/browser/extensions/extension_host.h
+++ b/chrome/browser/extensions/extension_host.h
@@ -125,6 +125,8 @@ class ExtensionHost : public RenderViewHostDelegate,
const ViewHostMsg_FrameNavigate_Params& params);
virtual void DidStopLoading();
virtual void DocumentAvailableInMainFrame(RenderViewHost* render_view_host);
+ virtual void DocumentOnLoadCompletedInMainFrame(
+ RenderViewHost* render_view_host);
virtual WebPreferences GetWebkitPrefs();
virtual void ProcessDOMUIMessage(const std::string& message,
diff --git a/chrome/browser/extensions/extension_popup_api.cc b/chrome/browser/extensions/extension_popup_api.cc
index a6f85f2..c8ef519 100644
--- a/chrome/browser/extensions/extension_popup_api.cc
+++ b/chrome/browser/extensions/extension_popup_api.cc
@@ -12,6 +12,9 @@
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/profile.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/renderer_host/render_view_host_delegate.h"
+#include "chrome/browser/renderer_host/render_widget_host_view.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/notification_details.h"
@@ -22,9 +25,6 @@
#include "gfx/point.h"
#if defined(TOOLKIT_VIEWS)
-#include "chrome/browser/renderer_host/render_view_host.h"
-#include "chrome/browser/renderer_host/render_view_host_delegate.h"
-#include "chrome/browser/renderer_host/render_widget_host_view.h"
#include "chrome/browser/views/extensions/extension_popup.h"
#include "views/view.h"
#include "views/focus/focus_manager.h"
@@ -42,6 +42,8 @@ namespace {
const char kBadAnchorArgument[] = "Invalid anchor argument.";
const char kInvalidURLError[] = "Invalid URL.";
const char kNotAnExtension[] = "Not an extension view.";
+const char kPopupsDisallowed[] =
+ "Popups are only supported from toolstrip or tab-contents views.";
// Keys.
const wchar_t kUrlKey[] = L"url";
@@ -70,7 +72,8 @@ const char kRectangleChrome[] = "rectangle";
// containing view or any of *its* children.
class ExtensionPopupHost : public ExtensionPopup::Observer,
public views::WidgetFocusChangeListener,
- public base::RefCounted<ExtensionPopupHost> {
+ public base::RefCounted<ExtensionPopupHost>,
+ public NotificationObserver {
public:
explicit ExtensionPopupHost(ExtensionFunctionDispatcher* dispatcher)
: dispatcher_(dispatcher), popup_(NULL) {
@@ -85,9 +88,18 @@ class ExtensionPopupHost : public ExtensionPopup::Observer,
void set_popup(ExtensionPopup* popup) {
popup_ = popup;
+
+ // Now that a popup has been assigned, listen for subsequent popups being
+ // created in the same extension - we want to disallow more than one
+ // concurrently displayed popup windows.
+ registrar_.Add(
+ this,
+ NotificationType::EXTENSION_HOST_CREATED,
+ Source<ExtensionProcessManager>(
+ dispatcher_->profile()->GetExtensionProcessManager()));
}
- // Overriden from ExtensionPopup::Observer
+ // Overridden from ExtensionPopup::Observer
virtual void ExtensionPopupClosed(ExtensionPopup* popup) {
// Unregister the automation resource routing registered upon host
// creation.
@@ -119,7 +131,7 @@ class ExtensionPopupHost : public ExtensionPopup::Observer,
Release(); // Balanced in ctor.
}
- // Overriden from views::WidgetFocusChangeListener
+ // Overridden from views::WidgetFocusChangeListener
virtual void NativeFocusWillChange(gfx::NativeView focused_before,
gfx::NativeView focused_now) {
// If no view is to be focused, then Chrome was deactivated, so hide the
@@ -156,6 +168,23 @@ class ExtensionPopupHost : public ExtensionPopup::Observer,
&ExtensionPopup::Close));
}
+ // Overridden from NotificationObserver
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ DCHECK(NotificationType::EXTENSION_HOST_CREATED == type);
+ if (NotificationType::EXTENSION_HOST_CREATED == type) {
+ Details<ExtensionHost> details_host(details);
+ // Disallow multiple pop-ups from the same extension, by closing
+ // the presently opened popup during construction of any new popups.
+ if (ViewType::EXTENSION_POPUP == details_host->GetRenderViewType() &&
+ popup_->host()->extension() == details_host->extension() &&
+ Details<ExtensionHost>(popup_->host()) != details) {
+ popup_->Close();
+ }
+ }
+ }
+
private:
// Returns the AutomationResourceRoutingDelegate interface for |dispatcher|.
static AutomationResourceRoutingDelegate*
@@ -177,6 +206,8 @@ class ExtensionPopupHost : public ExtensionPopup::Observer,
// A pointer to the popup.
ExtensionPopup* popup_;
+ NotificationRegistrar registrar_;
+
DISALLOW_COPY_AND_ASSIGN(ExtensionPopupHost);
};
#endif // TOOLKIT_VIEWS
@@ -211,6 +242,16 @@ void PopupShowFunction::Run() {
}
bool PopupShowFunction::RunImpl() {
+ // Popups may only be displayed from TAB_CONTENTS and EXTENSION_TOOLSTRIP
+ // views.
+ ViewType::Type view_type =
+ dispatcher()->render_view_host()->delegate()->GetRenderViewType();
+ if (ViewType::EXTENSION_TOOLSTRIP != view_type &&
+ ViewType::TAB_CONTENTS != view_type) {
+ error_ = kPopupsDisallowed;
+ return false;
+ }
+
EXTENSION_FUNCTION_VALIDATE(args_->IsType(Value::TYPE_LIST));
const ListValue* args = args_as_list();
@@ -272,7 +313,6 @@ bool PopupShowFunction::RunImpl() {
return false;
}
-#if defined(TOOLKIT_VIEWS)
gfx::Point origin(dom_left, dom_top);
if (!dispatcher()->render_view_host()->view()) {
error_ = kNotAnExtension;
@@ -284,14 +324,6 @@ bool PopupShowFunction::RunImpl() {
origin.Offset(content_bounds.x(), content_bounds.y());
gfx::Rect rect(origin.x(), origin.y(), dom_width, dom_height);
- // Pop-up from extension views (ExtensionShelf, etc.), and drop-down when
- // in a TabContents view.
- ViewType::Type view_type =
- dispatcher()->render_view_host()->delegate()->GetRenderViewType();
- BubbleBorder::ArrowLocation arrow_location =
- view_type == ViewType::TAB_CONTENTS ?
- BubbleBorder::TOP_LEFT : BubbleBorder::BOTTOM_LEFT;
-
// Get the correct native window to pass to ExtensionPopup.
// ExtensionFunctionDispatcher::Delegate may provide a custom implementation
// of this.
@@ -300,6 +332,13 @@ bool PopupShowFunction::RunImpl() {
if (!window)
window = GetCurrentBrowser()->window()->GetNativeHandle();
+#if defined(TOOLKIT_VIEWS)
+ // Pop-up from extension views (ExtensionShelf, etc.), and drop-down when
+ // in a TabContents view.
+ BubbleBorder::ArrowLocation arrow_location =
+ view_type == ViewType::TAB_CONTENTS ?
+ BubbleBorder::TOP_LEFT : BubbleBorder::BOTTOM_LEFT;
+
// ExtensionPopupHost manages it's own lifetime.
ExtensionPopupHost* popup_host = new ExtensionPopupHost(dispatcher());
popup_ = ExtensionPopup::Show(url,
@@ -329,6 +368,8 @@ void PopupShowFunction::Observe(NotificationType type,
type == NotificationType::EXTENSION_HOST_DESTROYED);
DCHECK(popup_ != NULL);
+ // Wait for notification that the popup view is ready (and onload has been
+ // called), before completing the API call.
if (popup_ && type == NotificationType::EXTENSION_POPUP_VIEW_READY &&
Details<ExtensionHost>(popup_->host()) == details) {
SendResponse(true);
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc
index 0cca1a9..38834ef 100644
--- a/chrome/browser/renderer_host/render_view_host.cc
+++ b/chrome/browser/renderer_host/render_view_host.cc
@@ -723,6 +723,8 @@ void RenderViewHost::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_DidStopLoading, OnMsgDidStopLoading)
IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentAvailableInMainFrame,
OnMsgDocumentAvailableInMainFrame)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentOnLoadCompletedInMainFrame,
+ OnMsgDocumentOnLoadCompletedInMainFrame)
IPC_MESSAGE_HANDLER(ViewHostMsg_DidLoadResourceFromMemoryCache,
OnMsgDidLoadResourceFromMemoryCache)
IPC_MESSAGE_HANDLER(ViewHostMsg_DidDisplayInsecureContent,
@@ -1051,6 +1053,10 @@ void RenderViewHost::OnMsgDocumentAvailableInMainFrame() {
delegate_->DocumentAvailableInMainFrame(this);
}
+void RenderViewHost::OnMsgDocumentOnLoadCompletedInMainFrame() {
+ delegate_->DocumentOnLoadCompletedInMainFrame(this);
+}
+
void RenderViewHost::OnMsgDidLoadResourceFromMemoryCache(
const GURL& url,
const std::string& frame_origin,
diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h
index b384d6d..ea1ba15 100644
--- a/chrome/browser/renderer_host/render_view_host.h
+++ b/chrome/browser/renderer_host/render_view_host.h
@@ -497,6 +497,7 @@ class RenderViewHost : public RenderWidgetHost {
void OnMsgDidStartLoading();
void OnMsgDidStopLoading();
void OnMsgDocumentAvailableInMainFrame();
+ void OnMsgDocumentOnLoadCompletedInMainFrame();
void OnMsgDidLoadResourceFromMemoryCache(const GURL& url,
const std::string& frame_origin,
const std::string& main_frame_origin,
diff --git a/chrome/browser/renderer_host/render_view_host_delegate.h b/chrome/browser/renderer_host/render_view_host_delegate.h
index 233099c..b8ca5f0 100644
--- a/chrome/browser/renderer_host/render_view_host_delegate.h
+++ b/chrome/browser/renderer_host/render_view_host_delegate.h
@@ -537,6 +537,10 @@ class RenderViewHostDelegate {
// the document has finished parsing.
virtual void DocumentAvailableInMainFrame(RenderViewHost* render_view_host) {}
+ // The onload handler in the RenderView's main frame has completed.
+ virtual void DocumentOnLoadCompletedInMainFrame(
+ RenderViewHost* render_view_host) {}
+
// The page wants to open a URL with the specified disposition.
virtual void RequestOpenURL(const GURL& url,
const GURL& referrer,
diff --git a/chrome/common/extensions/api/extension_api.json b/chrome/common/extensions/api/extension_api.json
index 5db6983..99e07f9 100644
--- a/chrome/common/extensions/api/extension_api.json
+++ b/chrome/common/extensions/api/extension_api.json
@@ -134,9 +134,9 @@
"properties": {
"type": {
"type": "string",
- "enum": ["tab", "infobar", "notification"],
+ "enum": ["tab", "infobar", "notification", "popup"],
"optional": true,
- "description": "The type of view to get. If omitted, returns all views (including background pages and tabs). Valid values: 'tab', 'infobar', 'notification'."
+ "description": "The type of view to get. If omitted, returns all views (including background pages and tabs). Valid values: 'tab', 'infobar', 'notification', 'popup'."
},
"windowId": {
"type": "integer",
diff --git a/chrome/common/extensions/docs/extension.html b/chrome/common/extensions/docs/extension.html
index 113b81a..3c7f0cb 100644
--- a/chrome/common/extensions/docs/extension.html
+++ b/chrome/common/extensions/docs/extension.html
@@ -1158,7 +1158,7 @@ For details, see
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>The type of view to get. If omitted, returns all views (including background pages and tabs). Valid values: 'tab', 'infobar', 'notification'.</dd>
+ <dd>The type of view to get. If omitted, returns all views (including background pages and tabs). Valid values: 'tab', 'infobar', 'notification', 'popup'.</dd>
<!-- OBJECT PROPERTIES -->
<dd style="display: none; ">
diff --git a/chrome/common/extensions/docs/history.html b/chrome/common/extensions/docs/history.html
index 7079c0c..a6bf9b1 100644
--- a/chrome/common/extensions/docs/history.html
+++ b/chrome/common/extensions/docs/history.html
@@ -266,9 +266,9 @@
<a href="#types">Types</a>
<ol>
<li>
- <a href="#type-VisitItem">VisitItem</a>
- </li><li>
<a href="#type-HistoryItem">HistoryItem</a>
+ </li><li>
+ <a href="#type-VisitItem">VisitItem</a>
</li>
</ol>
</li>
@@ -1874,8 +1874,8 @@ For other examples and for help in viewing the source code, see
<!-- iterates over all types -->
<div class="apiItem">
- <a name="type-VisitItem"></a>
- <h4>VisitItem</h4>
+ <a name="type-HistoryItem"></a>
+ <h4>HistoryItem</h4>
<div>
<dt>
@@ -1905,7 +1905,7 @@ For other examples and for help in viewing the source code, see
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>An object encapsulating one visit to a URL.</dd>
+ <dd>An object encapsulating one result of a history query.</dd>
<!-- OBJECT PROPERTIES -->
<dd>
@@ -1954,13 +1954,13 @@ For other examples and for help in viewing the source code, see
</div><div>
<div>
<dt>
- <var>visitId</var>
+ <var>url</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
- <span class="optional" style="display: none; ">optional</span>
+ <span class="optional">optional</span>
<span id="typeTemplate">
<span style="display: none; ">
<a> Type</a>
@@ -1980,7 +1980,7 @@ For other examples and for help in viewing the source code, see
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>The unique identifier for this visit.</dd>
+ <dd>The URL navigated to by a user.</dd>
<!-- OBJECT PROPERTIES -->
<dd style="display: none; ">
@@ -1995,7 +1995,7 @@ For other examples and for help in viewing the source code, see
</div><div>
<div>
<dt>
- <var>visitTime</var>
+ <var>title</var>
<em>
<!-- TYPE -->
@@ -2010,7 +2010,7 @@ For other examples and for help in viewing the source code, see
<span style="display: none; ">
array of <span><span></span></span>
</span>
- <span>number</span>
+ <span>string</span>
</span>
</span>
)
@@ -2021,7 +2021,7 @@ For other examples and for help in viewing the source code, see
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>When this visit occurred, represented in milliseconds since the epoch.</dd>
+ <dd>The title of the history page.</dd>
<!-- OBJECT PROPERTIES -->
<dd style="display: none; ">
@@ -2036,13 +2036,13 @@ For other examples and for help in viewing the source code, see
</div><div>
<div>
<dt>
- <var>referringVisitId</var>
+ <var>lastVisitTime</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
- <span class="optional" style="display: none; ">optional</span>
+ <span class="optional">optional</span>
<span id="typeTemplate">
<span style="display: none; ">
<a> Type</a>
@@ -2051,7 +2051,7 @@ For other examples and for help in viewing the source code, see
<span style="display: none; ">
array of <span><span></span></span>
</span>
- <span>string</span>
+ <span>number</span>
</span>
</span>
)
@@ -2062,7 +2062,7 @@ For other examples and for help in viewing the source code, see
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>The visit_id of the referrer.</dd>
+ <dd>When this page was last loaded, represented in milliseconds since the epoch.</dd>
<!-- OBJECT PROPERTIES -->
<dd style="display: none; ">
@@ -2077,13 +2077,13 @@ For other examples and for help in viewing the source code, see
</div><div>
<div>
<dt>
- <var>transition</var>
+ <var>visitCount</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
- <span class="optional" style="display: none; ">optional</span>
+ <span class="optional">optional</span>
<span id="typeTemplate">
<span style="display: none; ">
<a> Type</a>
@@ -2092,7 +2092,7 @@ For other examples and for help in viewing the source code, see
<span style="display: none; ">
array of <span><span></span></span>
</span>
- <span>string</span>
+ <span>integer</span>
</span>
</span>
)
@@ -2103,7 +2103,7 @@ For other examples and for help in viewing the source code, see
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>The <a href="#transition_types">transition type</a> for this visit from its referrer.</dd>
+ <dd>The number of times the user has navigated to this page.</dd>
<!-- OBJECT PROPERTIES -->
<dd style="display: none; ">
@@ -2115,24 +2115,16 @@ For other examples and for help in viewing the source code, see
</dl>
</dd>
</div>
- </div>
- </dl>
- </dd>
- </div>
-
- </div><div class="apiItem">
- <a name="type-HistoryItem"></a>
- <h4>HistoryItem</h4>
-
- <div>
+ </div><div>
+ <div>
<dt>
- <var style="display: none; ">paramName</var>
+ <var>typedCount</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
- <span class="optional" style="display: none; ">optional</span>
+ <span class="optional">optional</span>
<span id="typeTemplate">
<span style="display: none; ">
<a> Type</a>
@@ -2141,7 +2133,7 @@ For other examples and for help in viewing the source code, see
<span style="display: none; ">
array of <span><span></span></span>
</span>
- <span>object</span>
+ <span>integer</span>
</span>
</span>
)
@@ -2152,15 +2144,30 @@ For other examples and for help in viewing the source code, see
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>An object encapsulating one result of a history query.</dd>
+ <dd>The number of times the user has navigated to this page by typing in the address.</dd>
<!-- OBJECT PROPERTIES -->
- <dd>
+ <dd style="display: none; ">
<dl>
<div>
<div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+ </div>
+ </dl>
+ </dd>
+ </div>
+
+ </div><div class="apiItem">
+ <a name="type-VisitItem"></a>
+ <h4>VisitItem</h4>
+
+ <div>
<dt>
- <var>id</var>
+ <var style="display: none; ">paramName</var>
<em>
<!-- TYPE -->
@@ -2175,7 +2182,7 @@ For other examples and for help in viewing the source code, see
<span style="display: none; ">
array of <span><span></span></span>
</span>
- <span>string</span>
+ <span>object</span>
</span>
</span>
)
@@ -2186,28 +2193,21 @@ For other examples and for help in viewing the source code, see
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>The unique identifier for the item.</dd>
+ <dd>An object encapsulating one visit to a URL.</dd>
<!-- OBJECT PROPERTIES -->
- <dd style="display: none; ">
+ <dd>
<dl>
<div>
<div>
- </div>
- </div>
- </dl>
- </dd>
- </div>
- </div><div>
- <div>
<dt>
- <var>url</var>
+ <var>id</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
- <span class="optional">optional</span>
+ <span class="optional" style="display: none; ">optional</span>
<span id="typeTemplate">
<span style="display: none; ">
<a> Type</a>
@@ -2227,7 +2227,7 @@ For other examples and for help in viewing the source code, see
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>The URL navigated to by a user.</dd>
+ <dd>The unique identifier for the item.</dd>
<!-- OBJECT PROPERTIES -->
<dd style="display: none; ">
@@ -2242,13 +2242,13 @@ For other examples and for help in viewing the source code, see
</div><div>
<div>
<dt>
- <var>title</var>
+ <var>visitId</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
- <span class="optional">optional</span>
+ <span class="optional" style="display: none; ">optional</span>
<span id="typeTemplate">
<span style="display: none; ">
<a> Type</a>
@@ -2268,7 +2268,7 @@ For other examples and for help in viewing the source code, see
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>The title of the history page.</dd>
+ <dd>The unique identifier for this visit.</dd>
<!-- OBJECT PROPERTIES -->
<dd style="display: none; ">
@@ -2283,7 +2283,7 @@ For other examples and for help in viewing the source code, see
</div><div>
<div>
<dt>
- <var>lastVisitTime</var>
+ <var>visitTime</var>
<em>
<!-- TYPE -->
@@ -2309,7 +2309,7 @@ For other examples and for help in viewing the source code, see
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>When this page was last loaded, represented in milliseconds since the epoch.</dd>
+ <dd>When this visit occurred, represented in milliseconds since the epoch.</dd>
<!-- OBJECT PROPERTIES -->
<dd style="display: none; ">
@@ -2324,13 +2324,13 @@ For other examples and for help in viewing the source code, see
</div><div>
<div>
<dt>
- <var>visitCount</var>
+ <var>referringVisitId</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
- <span class="optional">optional</span>
+ <span class="optional" style="display: none; ">optional</span>
<span id="typeTemplate">
<span style="display: none; ">
<a> Type</a>
@@ -2339,7 +2339,7 @@ For other examples and for help in viewing the source code, see
<span style="display: none; ">
array of <span><span></span></span>
</span>
- <span>integer</span>
+ <span>string</span>
</span>
</span>
)
@@ -2350,7 +2350,7 @@ For other examples and for help in viewing the source code, see
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>The number of times the user has navigated to this page.</dd>
+ <dd>The visit_id of the referrer.</dd>
<!-- OBJECT PROPERTIES -->
<dd style="display: none; ">
@@ -2365,13 +2365,13 @@ For other examples and for help in viewing the source code, see
</div><div>
<div>
<dt>
- <var>typedCount</var>
+ <var>transition</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
- <span class="optional">optional</span>
+ <span class="optional" style="display: none; ">optional</span>
<span id="typeTemplate">
<span style="display: none; ">
<a> Type</a>
@@ -2380,7 +2380,7 @@ For other examples and for help in viewing the source code, see
<span style="display: none; ">
array of <span><span></span></span>
</span>
- <span>integer</span>
+ <span>string</span>
</span>
</span>
)
@@ -2391,7 +2391,7 @@ For other examples and for help in viewing the source code, see
<dd class="todo" style="display: none; ">
Undocumented.
</dd>
- <dd>The number of times the user has navigated to this page by typing in the address.</dd>
+ <dd>The <a href="#transition_types">transition type</a> for this visit from its referrer.</dd>
<!-- OBJECT PROPERTIES -->
<dd style="display: none; ">
diff --git a/chrome/common/notification_type.h b/chrome/common/notification_type.h
index d2463a5..a1ff31a 100644
--- a/chrome/common/notification_type.h
+++ b/chrome/common/notification_type.h
@@ -796,7 +796,10 @@ class NotificationType {
EXTENSION_BACKGROUND_PAGE_READY,
// Sent when a pop-up extension view is ready, so that notification may
- // be sent to pending callbacks.
+ // be sent to pending callbacks. Note that this notification is sent
+ // after all onload callbacks have been invoked in the main frame.
+ // The details is the ExtensionHost* hosted within the popup, and the source
+ // is a Profile*.
EXTENSION_POPUP_VIEW_READY,
// Sent when a browser action's state has changed. The source is the
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index d575873..54453fa 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -1064,6 +1064,10 @@ IPC_BEGIN_MESSAGES(ViewHost)
// finished.
IPC_MESSAGE_ROUTED0(ViewHostMsg_DocumentAvailableInMainFrame)
+ // Sent when after the onload handler has been invoked for the document
+ // in the toplevel frame.
+ IPC_MESSAGE_ROUTED0(ViewHostMsg_DocumentOnLoadCompletedInMainFrame)
+
// Sent when the renderer loads a resource from its memory cache.
// The security info is non empty if the resource was originally loaded over
// a secure connection.
diff --git a/chrome/renderer/extensions/extension_process_bindings.cc b/chrome/renderer/extensions/extension_process_bindings.cc
index a12ef09..43db444 100644
--- a/chrome/renderer/extensions/extension_process_bindings.cc
+++ b/chrome/renderer/extensions/extension_process_bindings.cc
@@ -297,7 +297,7 @@ class ExtensionImpl : public ExtensionBase {
if (0 == popup_matcher.views()->Length())
return v8::Undefined();
- DCHECK(popup_matcher.views()->Has(0));
+ DCHECK(1 == popup_matcher.views()->Length());
// Return the first view found.
return popup_matcher.views()->Get(v8::Integer::New(0));
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index abf23be..f756899 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -2730,7 +2730,8 @@ void RenderView::OnUserScriptIdleTriggered(WebFrame* frame) {
}
void RenderView::didHandleOnloadEvents(WebFrame* frame) {
- // Ignore
+ if (webview()->mainFrame() == frame)
+ Send(new ViewHostMsg_DocumentOnLoadCompletedInMainFrame(routing_id_));
}
void RenderView::didFailLoad(WebFrame* frame, const WebURLError& error) {
diff --git a/chrome/test/data/extensions/api_test/popup/toolband.html b/chrome/test/data/extensions/api_test/popup/toolband.html
index 5d04350..eb3fd43 100644
--- a/chrome/test/data/extensions/api_test/popup/toolband.html
+++ b/chrome/test/data/extensions/api_test/popup/toolband.html
@@ -111,8 +111,7 @@ window.onload = function() {
},
function popupBlackBorder() {
// Ensure that the test waits until the popup is dismissed.
- chrome.test.listenOnce(chrome.experimental.popup.onClosed,
- function() {});
+ chrome.test.listenOnce(chrome.experimental.popup.onClosed);
// Validate that displaying a pop-up with a black border still invokes
// the callback successfully. Note that this test does not validate
@@ -127,6 +126,62 @@ window.onload = function() {
chrome.experimental.extension.getPopupView().close();
}));
},
+ function disallowMultiplePopups() {
+ // This test ensures that for a given extension with a popup displayed,
+ // displaying a subsequent popup will dismiss the first.
+ var showDetails1 = {
+ "relativeTo": document.getElementById("anchorHere"),
+ };
+
+ var showDetails2 = {
+ "relativeTo": document.getElementById("anchorHere2"),
+ "borderStyle": "rectangle"
+ };
+
+ // Track the number of popups opened and closed, so that we can signal
+ // the test as completed when appropriate.
+ var numberClosed = 0;
+ var doneListening = chrome.test.listenForever(
+ chrome.experimental.popup.onClosed,
+ function() {
+ // This test expects to open and close two popups, so signify that
+ // the test has succeeded, after closing the second popup.
+ if (++numberClosed == 2) {
+ doneListening();
+ }
+ });
+
+ chrome.experimental.popup.show("toolband_popup_a.html",
+ showDetails1,
+ function() {
+ // Validate that the popup view returned is the one we expect.
+ chrome.test.assertEq(
+ 'a',
+ chrome.experimental.extension.getPopupView().getIdentity());
+
+ // Ensure that only one popup is open.
+ chrome.test.assertEq(
+ 1,
+ chrome.extension.getViews({type: "popup"}).length);
+
+ chrome.experimental.popup.show("toolband_popup_b.html",
+ showDetails2,
+ function() {
+ // Validate that the first popup view is fully closed, and that
+ // getPopupView returns the most recently opened popup.
+ chrome.test.assertEq(
+ 'b',
+ chrome.experimental.extension.getPopupView().getIdentity());
+
+ // Ensure that only one popup is open.
+ chrome.test.assertEq(
+ 1,
+ chrome.extension.getViews({type: 'popup'}).length);
+
+ chrome.experimental.extension.getPopupView().close();
+ });
+ });
+ },
function popupChromeSizing() {
// Ensure that the test waits until the popup is dismissed.
chrome.test.listenOnce(chrome.experimental.popup.onClosed);
@@ -159,8 +214,11 @@ window.onload = function() {
</script>
</head>
<body>
-<div>
-<span id="anchorHere">TEST</span>
+<div id="anchorHere">
+<span>TEST</span>
+</div>
+<div id="anchorHere2">
+<span>TESTING 2</span>
</div>
<form>
<input id="entryForm" onfocus="onFormFocused();" onblur="onFormBlurred();"/>
diff --git a/chrome/test/data/extensions/api_test/popup/toolband_popup_a.html b/chrome/test/data/extensions/api_test/popup/toolband_popup_a.html
new file mode 100644
index 0000000..09979f1
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/popup/toolband_popup_a.html
@@ -0,0 +1,12 @@
+<html>
+<head>
+<script>
+function getIdentity() {
+ return 'a';
+}
+</script>
+</head>
+<body>
+Popup-A-Contents
+</body>
+</html> \ No newline at end of file
diff --git a/chrome/test/data/extensions/api_test/popup/toolband_popup_b.html b/chrome/test/data/extensions/api_test/popup/toolband_popup_b.html
new file mode 100644
index 0000000..82f24aa
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/popup/toolband_popup_b.html
@@ -0,0 +1,12 @@
+<html>
+<head>
+<script>
+function getIdentity() {
+ return 'b';
+}
+</script>
+</head>
+<body>
+Popup-B-Contents
+</body>
+</html> \ No newline at end of file