summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/automation/automation_provider_observers.cc22
-rw-r--r--chrome/browser/renderer_host/resource_dispatcher_host.cc15
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.cc16
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.h7
-rw-r--r--chrome/browser/renderer_host/resource_request_details.h14
-rw-r--r--chrome/browser/worker_host/worker_document_set.cc64
-rw-r--r--chrome/browser/worker_host/worker_document_set.h85
-rw-r--r--chrome/browser/worker_host/worker_process_host.cc117
-rw-r--r--chrome/browser/worker_host/worker_process_host.h53
-rw-r--r--chrome/browser/worker_host/worker_service.cc64
-rw-r--r--chrome/browser/worker_host/worker_service.h9
-rwxr-xr-xchrome/chrome_browser.gypi2
-rw-r--r--chrome/common/render_messages.h52
-rw-r--r--chrome/common/render_messages_internal.h10
-rw-r--r--chrome/renderer/render_view.cc3
-rw-r--r--chrome/renderer/websharedworker_proxy.cc3
-rw-r--r--chrome/renderer/websharedworker_proxy.h1
-rw-r--r--chrome/renderer/webworker_base.cc12
-rw-r--r--chrome/renderer/webworker_base.h5
-rw-r--r--chrome/renderer/webworker_proxy.cc4
-rw-r--r--chrome/test/data/workers/shared_worker_auth.html18
-rw-r--r--chrome/test/data/workers/worker_auth.html18
-rw-r--r--chrome/test/data/workers/worker_common.js2
-rw-r--r--chrome/worker/worker_uitest.cc36
-rw-r--r--tools/valgrind/memcheck/suppressions.txt6
25 files changed, 475 insertions, 163 deletions
diff --git a/chrome/browser/automation/automation_provider_observers.cc b/chrome/browser/automation/automation_provider_observers.cc
index 03039b1..dfea17c 100644
--- a/chrome/browser/automation/automation_provider_observers.cc
+++ b/chrome/browser/automation/automation_provider_observers.cc
@@ -174,18 +174,16 @@ void NavigationNotificationObserver::Observe(
// occur while authentication is ongoing.
navigation_started_ = true;
} else if (type == NotificationType::AUTH_NEEDED) {
- if (navigation_started_) {
- // Remember the login handler that wants authentication.
- LoginHandler* handler =
- Details<LoginNotificationDetails>(details)->handler();
- automation_->AddLoginHandler(controller_, handler);
-
- // Respond that authentication is needed.
- navigation_started_ = false;
- ConditionMet(AUTOMATION_MSG_NAVIGATION_AUTH_NEEDED);
- } else {
- NOTREACHED();
- }
+ // Remember the login handler that wants authentication.
+ // We do this in all cases (not just when navigation_started_ == true) so
+ // tests can still wait for auth dialogs outside of navigation.
+ LoginHandler* handler =
+ Details<LoginNotificationDetails>(details)->handler();
+ automation_->AddLoginHandler(controller_, handler);
+
+ // Respond that authentication is needed.
+ navigation_started_ = false;
+ ConditionMet(AUTOMATION_MSG_NAVIGATION_AUTH_NEEDED);
} else {
NOTREACHED();
}
diff --git a/chrome/browser/renderer_host/resource_dispatcher_host.cc b/chrome/browser/renderer_host/resource_dispatcher_host.cc
index 65182c2..2907d7f 100644
--- a/chrome/browser/renderer_host/resource_dispatcher_host.cc
+++ b/chrome/browser/renderer_host/resource_dispatcher_host.cc
@@ -159,7 +159,11 @@ class RVHDelegateNotificationTask : public Task {
if (!ResourceDispatcherHost::RenderViewForRequest(request,
&render_process_host_id_,
&render_view_host_id_)) {
- NOTREACHED();
+ // Issue a warning here - this can happen during normal operation (for
+ // example, if a worker exits while a network operation is pending), but
+ // it should be fairly rare.
+ DLOG(WARNING) << "Trying to deliver a message to a RenderViewHost" <<
+ " that has already exited or has never existed.";
}
}
@@ -1451,8 +1455,13 @@ bool ResourceDispatcherHost::RenderViewForRequest(const URLRequest* request,
*render_view_host_id = -1;
return false;
}
- *render_process_host_id = worker_instance->renderer_id();
- *render_view_host_id = worker_instance->render_view_route_id();
+ DCHECK(!worker_instance->worker_document_set()->IsEmpty());
+ const WorkerDocumentSet::DocumentInfoSet& parents =
+ worker_instance->worker_document_set()->documents();
+ // Need to display some related UI for this network request - pick an
+ // arbitrary parent to do so.
+ *render_process_host_id = parents.begin()->renderer_id();
+ *render_view_host_id = parents.begin()->render_view_route_id();
} else {
*render_process_host_id = info->child_id();
*render_view_host_id = info->route_id();
diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc
index 11d7091..4313dbd 100644
--- a/chrome/browser/renderer_host/resource_message_filter.cc
+++ b/chrome/browser/renderer_host/resource_message_filter.cc
@@ -636,26 +636,24 @@ void ResourceMessageFilter::OnLaunchNaCl(
host->Launch(this, channel_descriptor, reply_msg);
}
-void ResourceMessageFilter::OnCreateWorker(const GURL& url,
- bool is_shared,
- const string16& name,
- int render_view_route_id,
- int* route_id) {
+void ResourceMessageFilter::OnCreateWorker(
+ const ViewHostMsg_CreateWorker_Params& params, int* route_id) {
*route_id = render_widget_helper_->GetNextRoutingID();
WorkerService::GetInstance()->CreateWorker(
- url, is_shared, off_the_record(), name, id(), render_view_route_id, this,
- *route_id);
+ params.url, params.is_shared, off_the_record(), params.name,
+ params.document_id, id(), params.render_view_route_id, this, *route_id);
}
void ResourceMessageFilter::OnLookupSharedWorker(const GURL& url,
const string16& name,
unsigned long long document_id,
+ int render_view_route_id,
int* route_id,
bool* url_mismatch) {
int new_route_id = render_widget_helper_->GetNextRoutingID();
bool worker_found = WorkerService::GetInstance()->LookupSharedWorker(
- url, name, off_the_record(), document_id, this, new_route_id,
- url_mismatch);
+ url, name, off_the_record(), document_id, id(), render_view_route_id,
+ this, new_route_id, url_mismatch);
*route_id = worker_found ? new_route_id : MSG_ROUTING_NONE;
}
diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h
index 585995f..7cd1251 100644
--- a/chrome/browser/renderer_host/resource_message_filter.h
+++ b/chrome/browser/renderer_host/resource_message_filter.h
@@ -44,6 +44,7 @@ class Profile;
class RenderWidgetHelper;
class URLRequestContextGetter;
struct ViewHostMsg_Audio_CreateStream;
+struct ViewHostMsg_CreateWorker_Params;
struct WebPluginInfo;
namespace printing {
@@ -166,14 +167,12 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
void OnLaunchNaCl(const std::wstring& url,
int channel_descriptor,
IPC::Message* reply_msg);
- void OnCreateWorker(const GURL& url,
- bool is_shared,
- const string16& name,
- int render_view_route_id,
+ void OnCreateWorker(const ViewHostMsg_CreateWorker_Params& params,
int* route_id);
void OnLookupSharedWorker(const GURL& url,
const string16& name,
unsigned long long document_id,
+ int render_view_route_id,
int* route_id,
bool* url_error);
void OnDocumentDetached(unsigned long long document_id);
diff --git a/chrome/browser/renderer_host/resource_request_details.h b/chrome/browser/renderer_host/resource_request_details.h
index c34af0f..ad0df97d 100644
--- a/chrome/browser/renderer_host/resource_request_details.h
+++ b/chrome/browser/renderer_host/resource_request_details.h
@@ -46,8 +46,18 @@ class ResourceRequestDetails {
// such as ssl state etc.
const WorkerProcessHost::WorkerInstance* worker_instance =
WorkerService::GetInstance()->FindWorkerInstance(info->child_id());
- origin_child_id_ =
- worker_instance ? worker_instance->renderer_id() : info->child_id();
+ if (worker_instance) {
+ DCHECK(!worker_instance->worker_document_set()->IsEmpty());
+ const WorkerDocumentSet::DocumentInfoSet& parents =
+ worker_instance->worker_document_set()->documents();
+ // TODO(atwilson): need to notify all associated renderers in the case
+ // of ssl state change (http://crbug.com/25357). For now, just notify
+ // the first one (works for dedicated workers and shared workers with
+ // a single process).
+ origin_child_id_ = parents.begin()->renderer_id();
+ } else {
+ origin_child_id_ = info->child_id();
+ }
}
virtual ~ResourceRequestDetails() {}
diff --git a/chrome/browser/worker_host/worker_document_set.cc b/chrome/browser/worker_host/worker_document_set.cc
new file mode 100644
index 0000000..2e4d9aa
--- /dev/null
+++ b/chrome/browser/worker_host/worker_document_set.cc
@@ -0,0 +1,64 @@
+// Copyright (c) 2009 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/worker_host/worker_document_set.h"
+
+WorkerDocumentSet::WorkerDocumentSet() {
+}
+
+void WorkerDocumentSet::Add(IPC::Message::Sender* parent,
+ unsigned long long document_id,
+ int renderer_id,
+ int render_view_route_id) {
+ DocumentInfo info(parent, document_id, renderer_id, render_view_route_id);
+ document_set_.insert(info);
+}
+
+bool WorkerDocumentSet::Contains(IPC::Message::Sender* parent,
+ unsigned long long document_id) const {
+ for (DocumentInfoSet::const_iterator i = document_set_.begin();
+ i != document_set_.end(); ++i) {
+ if (i->sender() == parent && i->document_id() == document_id)
+ return true;
+ }
+ return false;
+}
+
+void WorkerDocumentSet::Remove(IPC::Message::Sender* parent,
+ unsigned long long document_id) {
+ for (DocumentInfoSet::iterator i = document_set_.begin();
+ i != document_set_.end(); i++) {
+ if (i->sender() == parent && i->document_id() == document_id) {
+ document_set_.erase(i);
+ break;
+ }
+ }
+ // Should not be duplicate copies in the document set.
+ DCHECK(!Contains(parent, document_id));
+}
+
+void WorkerDocumentSet::RemoveAll(IPC::Message::Sender* parent) {
+ for (DocumentInfoSet::iterator i = document_set_.begin();
+ i != document_set_.end();) {
+
+ // Note this idiom is somewhat tricky - calling document_set_.erase(iter)
+ // invalidates any iterators that point to the element being removed, so
+ // bump the iterator beyond the item being removed before calling erase.
+ if (i->sender() == parent) {
+ DocumentInfoSet::iterator item_to_delete = i++;
+ document_set_.erase(item_to_delete);
+ } else {
+ ++i;
+ }
+ }
+}
+
+WorkerDocumentSet::DocumentInfo::DocumentInfo(
+ IPC::Message::Sender* sender, unsigned long long document_id,
+ int renderer_id, int render_view_route_id)
+ : sender_(sender),
+ document_id_(document_id),
+ renderer_id_(renderer_id),
+ render_view_route_id_(render_view_route_id) {
+}
diff --git a/chrome/browser/worker_host/worker_document_set.h b/chrome/browser/worker_host/worker_document_set.h
new file mode 100644
index 0000000..57c1669
--- /dev/null
+++ b/chrome/browser/worker_host/worker_document_set.h
@@ -0,0 +1,85 @@
+// Copyright (c) 2009 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_WORKER_HOST_WORKER_DOCUMENT_SET_H_
+#define CHROME_BROWSER_WORKER_HOST_WORKER_DOCUMENT_SET_H_
+
+#include <set>
+
+#include "base/basictypes.h"
+#include "base/ref_counted.h"
+#include "ipc/ipc_message.h"
+
+// The WorkerDocumentSet tracks all of the DOM documents associated with a
+// set of workers. With nested workers, multiple workers can share the same
+// WorkerDocumentSet (meaning that they all share the same lifetime, and will
+// all exit when the last document in that set exits, per the WebWorkers spec).
+class WorkerDocumentSet : public base::RefCounted<WorkerDocumentSet> {
+ public:
+ WorkerDocumentSet();
+
+ // The information we track for each document
+ class DocumentInfo {
+ public:
+ DocumentInfo(IPC::Message::Sender* sender, unsigned long long document_id,
+ int renderer_id, int render_view_route_id);
+ IPC::Message::Sender* sender() const { return sender_; }
+ unsigned long long document_id() const { return document_id_; }
+ int renderer_id() const { return renderer_id_; }
+ int render_view_route_id() const { return render_view_route_id_; }
+
+ // Define operator "<", which is used to determine uniqueness within
+ // the set.
+ bool operator <(DocumentInfo other) const {
+ // Items are identical if the sender and document_id are identical,
+ // otherwise create an arbitrary stable ordering based on the document
+ // id/sender.
+ if (sender() == other.sender()) {
+ return document_id() < other.document_id();
+ } else {
+ return reinterpret_cast<unsigned long long>(sender()) <
+ reinterpret_cast<unsigned long long>(other.sender());
+ }
+ }
+
+ private:
+ IPC::Message::Sender* sender_;
+ unsigned long long document_id_;
+ int renderer_id_;
+ int render_view_route_id_;
+ };
+
+ // Adds a document to a shared worker's document set. Also includes the
+ // associated renderer_id the document is associated with, to enable
+ // communication with the parent tab for things like http auth dialogs.
+ void Add(IPC::Message::Sender* parent,
+ unsigned long long document_id,
+ int renderer_id,
+ int render_view_route_id);
+
+ // Checks to see if a document is in a shared worker's document set.
+ bool Contains(IPC::Message::Sender* parent,
+ unsigned long long document_id) const;
+
+ // Removes a specific document from a worker's document set when that document
+ // is detached.
+ void Remove(IPC::Message::Sender* parent, unsigned long long document_id);
+
+ // Invoked when a render process exits, to remove all associated documents
+ // from a worker's document set.
+ void RemoveAll(IPC::Message::Sender* parent);
+
+ bool IsEmpty() const { return document_set_.empty(); }
+
+ // Define a typedef for convenience here when declaring iterators, etc.
+ typedef std::set<DocumentInfo> DocumentInfoSet;
+
+ // Returns the set of documents associated with this worker.
+ const DocumentInfoSet& documents() { return document_set_; }
+
+ private:
+ DocumentInfoSet document_set_;
+};
+
+#endif // CHROME_BROWSER_WORKER_HOST_WORKER_DOCUMENT_SET_H_
diff --git a/chrome/browser/worker_host/worker_process_host.cc b/chrome/browser/worker_host/worker_process_host.cc
index 562daea..4f6d5ae 100644
--- a/chrome/browser/worker_host/worker_process_host.cc
+++ b/chrome/browser/worker_host/worker_process_host.cc
@@ -65,11 +65,17 @@ WorkerProcessHost::~WorkerProcessHost() {
Source<WorkerProcessHost>(this),
NotificationService::NoDetails());
- // If we crashed, tell the RenderViewHost.
+ // If we crashed, tell the RenderViewHosts.
for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) {
- ChromeThread::PostTask(
- ChromeThread::UI, FROM_HERE,
- new WorkerCrashTask(i->renderer_id(), i->render_view_route_id()));
+ const WorkerDocumentSet::DocumentInfoSet& parents =
+ i->worker_document_set()->documents();
+ for (WorkerDocumentSet::DocumentInfoSet::const_iterator parent_iter =
+ parents.begin(); parent_iter != parents.end(); ++parent_iter) {
+ ChromeThread::PostTask(
+ ChromeThread::UI, FROM_HERE,
+ new WorkerCrashTask(parent_iter->renderer_id(),
+ parent_iter->render_view_route_id()));
+ }
}
ChildProcessSecurityPolicy::GetInstance()->Remove(id());
@@ -331,8 +337,8 @@ void WorkerProcessHost::SenderShutdown(IPC::Message::Sender* sender) {
bool shutdown = false;
i->RemoveSenders(sender);
if (i->shared()) {
- i->RemoveAllAssociatedDocuments(sender);
- if (i->IsDocumentSetEmpty()) {
+ i->worker_document_set()->RemoveAll(sender);
+ if (i->worker_document_set()->IsEmpty()) {
shutdown = true;
}
} else if (i->NumSenders() == 0) {
@@ -375,28 +381,37 @@ void WorkerProcessHost::UpdateTitle() {
void WorkerProcessHost::OnLookupSharedWorker(const GURL& url,
const string16& name,
unsigned long long document_id,
+ int render_view_route_id,
int* route_id,
bool* url_mismatch) {
int new_route_id = WorkerService::GetInstance()->next_worker_route_id();
- // TODO(atwilson): Add code to merge document sets for nested shared workers.
+ // TODO(atwilson): Add code to pass in the current worker's document set for
+ // these nested workers. Code below will not work for SharedWorkers as it
+ // only looks at a single parent.
+ DCHECK(instances_.front().worker_document_set()->documents().size() == 1);
+ WorkerDocumentSet::DocumentInfoSet::const_iterator first_parent =
+ instances_.front().worker_document_set()->documents().begin();
bool worker_found = WorkerService::GetInstance()->LookupSharedWorker(
- url, name, instances_.front().off_the_record(), document_id, this,
+ url, name, instances_.front().off_the_record(), document_id,
+ first_parent->renderer_id(), first_parent->render_view_route_id(), this,
new_route_id, url_mismatch);
*route_id = worker_found ? new_route_id : MSG_ROUTING_NONE;
}
-void WorkerProcessHost::OnCreateWorker(const GURL& url,
- bool shared,
- const string16& name,
- int render_view_route_id,
- int* route_id) {
+void WorkerProcessHost::OnCreateWorker(
+ const ViewHostMsg_CreateWorker_Params& params, int* route_id) {
DCHECK(instances_.size() == 1); // Only called when one process per worker.
+ // TODO(atwilson): Add code to pass in the current worker's document set for
+ // these nested workers. Code below will not work for SharedWorkers as it
+ // only looks at a single parent.
+ DCHECK(instances_.front().worker_document_set()->documents().size() == 1);
+ WorkerDocumentSet::DocumentInfoSet::const_iterator first_parent =
+ instances_.front().worker_document_set()->documents().begin();
*route_id = WorkerService::GetInstance()->next_worker_route_id();
WorkerService::GetInstance()->CreateWorker(
- url, shared, instances_.front().off_the_record(), name,
- instances_.front().renderer_id(),
- instances_.front().render_view_route_id(), this, *route_id);
- // TODO(atwilson): Add code to merge document sets for nested shared workers.
+ params.url, params.is_shared, instances_.front().off_the_record(),
+ params.name, params.document_id, first_parent->renderer_id(),
+ first_parent->render_view_route_id(), this, *route_id);
}
void WorkerProcessHost::OnCancelCreateDedicatedWorker(int route_id) {
@@ -415,8 +430,8 @@ void WorkerProcessHost::DocumentDetached(IPC::Message::Sender* parent,
if (!i->shared()) {
++i;
} else {
- i->RemoveFromDocumentSet(parent, document_id);
- if (i->IsDocumentSetEmpty()) {
+ i->worker_document_set()->Remove(parent, document_id);
+ if (i->worker_document_set()->IsEmpty()) {
// This worker has no more associated documents - shut it down.
Send(new WorkerMsg_TerminateWorkerContext(i->worker_route_id()));
i = instances_.erase(i);
@@ -431,17 +446,14 @@ WorkerProcessHost::WorkerInstance::WorkerInstance(const GURL& url,
bool shared,
bool off_the_record,
const string16& name,
- int renderer_id,
- int render_view_route_id,
int worker_route_id)
: url_(url),
shared_(shared),
off_the_record_(off_the_record),
closed_(false),
name_(name),
- renderer_id_(renderer_id),
- render_view_route_id_(render_view_route_id),
- worker_route_id_(worker_route_id) {
+ worker_route_id_(worker_route_id),
+ worker_document_set_(new WorkerDocumentSet()) {
}
// Compares an instance based on the algorithm in the WebWorkers spec - an
@@ -469,48 +481,6 @@ bool WorkerProcessHost::WorkerInstance::Matches(
return name_ == match_name;
}
-void WorkerProcessHost::WorkerInstance::AddToDocumentSet(
- IPC::Message::Sender* parent, unsigned long long document_id) {
- if (!IsInDocumentSet(parent, document_id)) {
- DocumentInfo info(parent, document_id);
- document_set_.push_back(info);
- }
-}
-
-bool WorkerProcessHost::WorkerInstance::IsInDocumentSet(
- IPC::Message::Sender* parent, unsigned long long document_id) const {
- for (DocumentSet::const_iterator i = document_set_.begin();
- i != document_set_.end(); ++i) {
- if (i->first == parent && i->second == document_id)
- return true;
- }
- return false;
-}
-
-void WorkerProcessHost::WorkerInstance::RemoveFromDocumentSet(
- IPC::Message::Sender* parent, unsigned long long document_id) {
- for (DocumentSet::iterator i = document_set_.begin();
- i != document_set_.end(); i++) {
- if (i->first == parent && i->second == document_id) {
- document_set_.erase(i);
- break;
- }
- }
- // Should not be duplicate copies in the document set.
- DCHECK(!IsInDocumentSet(parent, document_id));
-}
-
-void WorkerProcessHost::WorkerInstance::RemoveAllAssociatedDocuments(
- IPC::Message::Sender* parent) {
- for (DocumentSet::iterator i = document_set_.begin();
- i != document_set_.end();) {
- if (i->first == parent)
- i = document_set_.erase(i);
- else
- ++i;
- }
-}
-
void WorkerProcessHost::WorkerInstance::AddSender(IPC::Message::Sender* sender,
int sender_route_id) {
if (!HasSender(sender, sender_route_id)) {
@@ -553,6 +523,21 @@ bool WorkerProcessHost::WorkerInstance::HasSender(
return false;
}
+bool WorkerProcessHost::WorkerInstance::RendererIsParent(
+ int renderer_id, int render_view_route_id) const {
+ const WorkerDocumentSet::DocumentInfoSet& parents =
+ worker_document_set()->documents();
+ for (WorkerDocumentSet::DocumentInfoSet::const_iterator parent_iter =
+ parents.begin();
+ parent_iter != parents.end(); ++parent_iter) {
+ if (parent_iter->renderer_id() == renderer_id &&
+ parent_iter->render_view_route_id() == render_view_route_id) {
+ return true;
+ }
+ }
+ return false;
+}
+
WorkerProcessHost::WorkerInstance::SenderInfo
WorkerProcessHost::WorkerInstance::GetSender() const {
DCHECK(NumSenders() == 1);
diff --git a/chrome/browser/worker_host/worker_process_host.h b/chrome/browser/worker_host/worker_process_host.h
index 1834725..b5a8d74f 100644
--- a/chrome/browser/worker_host/worker_process_host.h
+++ b/chrome/browser/worker_host/worker_process_host.h
@@ -9,12 +9,16 @@
#include "base/basictypes.h"
#include "base/task.h"
+#include "chrome/browser/worker_host/worker_document_set.h"
#include "chrome/common/child_process_host.h"
#include "googleurl/src/gurl.h"
#include "ipc/ipc_channel.h"
+struct ViewHostMsg_CreateWorker_Params;
+
class WorkerProcessHost : public ChildProcessHost {
public:
+
// Contains information about each worker instance, needed to forward messages
// between the renderer and worker processes.
class WorkerInstance {
@@ -23,8 +27,6 @@ class WorkerProcessHost : public ChildProcessHost {
bool shared,
bool off_the_record,
const string16& name,
- int renderer_id,
- int render_view_route_id,
int worker_route_id);
// Unique identifier for a worker client.
@@ -35,6 +37,7 @@ class WorkerProcessHost : public ChildProcessHost {
void RemoveSender(IPC::Message::Sender* sender, int sender_route_id);
void RemoveSenders(IPC::Message::Sender* sender);
bool HasSender(IPC::Message::Sender* sender, int sender_route_id) const;
+ bool RendererIsParent(int renderer_id, int render_view_route_id) const;
int NumSenders() const { return senders_.size(); }
// Returns the single sender (must only be one).
SenderInfo GetSender() const;
@@ -45,31 +48,13 @@ class WorkerProcessHost : public ChildProcessHost {
bool Matches(
const GURL& url, const string16& name, bool off_the_record) const;
- // Adds a document to a shared worker's document set.
- void AddToDocumentSet(IPC::Message::Sender* parent,
- unsigned long long document_id);
-
- // Checks to see if a document is in a shared worker's document set.
- bool IsInDocumentSet(IPC::Message::Sender* parent,
- unsigned long long document_id) const;
-
- // Removes a specific document from a shared worker's document set when
- // that document is detached.
- void RemoveFromDocumentSet(IPC::Message::Sender* parent,
- unsigned long long document_id);
-
- // Copies the document set from one instance to another
- void CopyDocumentSet(const WorkerInstance& instance) {
- document_set_ = instance.document_set_;
+ // Shares the passed instance's WorkerDocumentSet with this instance. This
+ // instance's current WorkerDocumentSet is dereferenced (and freed if this
+ // is the only reference) as a result.
+ void ShareDocumentSet(const WorkerInstance& instance) {
+ worker_document_set_ = instance.worker_document_set_;
};
- // Invoked when a render process exits, to remove all associated documents
- // from a shared worker's document set.
- void RemoveAllAssociatedDocuments(IPC::Message::Sender* parent);
-
- bool IsDocumentSetEmpty() const { return document_set_.empty(); }
-
-
// Accessors
bool shared() const { return shared_; }
bool off_the_record() const { return off_the_record_; }
@@ -77,14 +62,12 @@ class WorkerProcessHost : public ChildProcessHost {
void set_closed(bool closed) { closed_ = closed; }
const GURL& url() const { return url_; }
const string16 name() const { return name_; }
- int renderer_id() const { return renderer_id_; }
- int render_view_route_id() const { return render_view_route_id_; }
int worker_route_id() const { return worker_route_id_; }
+ WorkerDocumentSet* worker_document_set() const {
+ return worker_document_set_;
+ }
private:
- // Unique identifier for an associated document.
- typedef std::pair<IPC::Message::Sender*, unsigned long long> DocumentInfo;
- typedef std::list<DocumentInfo> DocumentSet;
// Set of all senders (clients) associated with this worker.
typedef std::list<SenderInfo> SenderList;
GURL url_;
@@ -92,11 +75,9 @@ class WorkerProcessHost : public ChildProcessHost {
bool off_the_record_;
bool closed_;
string16 name_;
- int renderer_id_;
- int render_view_route_id_;
int worker_route_id_;
SenderList senders_;
- DocumentSet document_set_;
+ scoped_refptr<WorkerDocumentSet> worker_document_set_;
};
explicit WorkerProcessHost(ResourceDispatcherHost* resource_dispatcher_host);
@@ -142,6 +123,7 @@ class WorkerProcessHost : public ChildProcessHost {
void OnLookupSharedWorker(const GURL& url,
const string16& name,
unsigned long long document_id,
+ int render_view_route_id,
int* route_id,
bool* url_error);
@@ -161,10 +143,7 @@ class WorkerProcessHost : public ChildProcessHost {
// Updates the title shown in the task manager.
void UpdateTitle();
- void OnCreateWorker(const GURL& url,
- bool shared,
- const string16& name,
- int render_view_route_id,
+ void OnCreateWorker(const ViewHostMsg_CreateWorker_Params& params,
int* route_id);
void OnCancelCreateDedicatedWorker(int route_id);
void OnForwardToWorker(const IPC::Message& message);
diff --git a/chrome/browser/worker_host/worker_service.cc b/chrome/browser/worker_host/worker_service.cc
index fe768c3..ffdbb1d 100644
--- a/chrome/browser/worker_host/worker_service.cc
+++ b/chrome/browser/worker_host/worker_service.cc
@@ -49,6 +49,7 @@ bool WorkerService::CreateWorker(const GURL &url,
bool is_shared,
bool off_the_record,
const string16& name,
+ unsigned long long document_id,
int renderer_id,
int render_view_route_id,
IPC::Message::Sender* sender,
@@ -61,10 +62,10 @@ bool WorkerService::CreateWorker(const GURL &url,
is_shared,
off_the_record,
name,
- renderer_id,
- render_view_route_id,
next_worker_route_id());
instance.AddSender(sender, sender_route_id);
+ instance.worker_document_set()->Add(
+ sender, document_id, renderer_id, render_view_route_id);
WorkerProcessHost* worker = NULL;
if (CommandLine::ForCurrentProcess()->HasSwitch(
@@ -89,6 +90,7 @@ bool WorkerService::CreateWorker(const GURL &url,
// If this worker is already running, no need to create a new copy. Just
// inform the caller that the worker has been created.
if (existing_instance) {
+ // TODO(atwilson): Change this to scan the sender list (crbug.com/29243).
existing_instance->AddSender(sender, sender_route_id);
sender->Send(new ViewMsg_WorkerCreated(sender_route_id));
return true;
@@ -108,8 +110,8 @@ bool WorkerService::CreateWorker(const GURL &url,
// Assign the accumulated document set and sender list for this pending
// worker to the new instance.
- DCHECK(!pending->IsDocumentSetEmpty());
- instance.CopyDocumentSet(*pending);
+ DCHECK(!pending->worker_document_set()->IsEmpty());
+ instance.ShareDocumentSet(*pending);
RemovePendingInstance(url, name, off_the_record);
}
@@ -129,6 +131,8 @@ bool WorkerService::LookupSharedWorker(const GURL &url,
const string16& name,
bool off_the_record,
unsigned long long document_id,
+ int renderer_id,
+ int render_view_route_id,
IPC::Message::Sender* sender,
int sender_route_id,
bool* url_mismatch) {
@@ -160,7 +164,8 @@ bool WorkerService::LookupSharedWorker(const GURL &url,
instance->AddSender(sender, sender_route_id);
// Add the passed sender/document_id to the worker instance.
- instance->AddToDocumentSet(sender, document_id);
+ instance->worker_document_set()->Add(
+ sender, document_id, renderer_id, render_view_route_id);
return found_instance;
}
@@ -176,8 +181,8 @@ void WorkerService::DocumentDetached(IPC::Message::Sender* sender,
for (WorkerProcessHost::Instances::iterator iter = queued_workers_.begin();
iter != queued_workers_.end();) {
if (iter->shared()) {
- iter->RemoveFromDocumentSet(sender, document_id);
- if (iter->IsDocumentSetEmpty()) {
+ iter->worker_document_set()->Remove(sender, document_id);
+ if (iter->worker_document_set()->IsEmpty()) {
iter = queued_workers_.erase(iter);
continue;
}
@@ -189,8 +194,8 @@ void WorkerService::DocumentDetached(IPC::Message::Sender* sender,
for (WorkerProcessHost::Instances::iterator iter =
pending_shared_workers_.begin();
iter != pending_shared_workers_.end(); ) {
- iter->RemoveFromDocumentSet(sender, document_id);
- if (iter->IsDocumentSetEmpty()) {
+ iter->worker_document_set()->Remove(sender, document_id);
+ if (iter->worker_document_set()->IsEmpty()) {
iter = pending_shared_workers_.erase(iter);
} else {
++iter;
@@ -294,8 +299,35 @@ WorkerProcessHost* WorkerService::GetLeastLoadedWorker() {
bool WorkerService::CanCreateWorkerProcess(
const WorkerProcessHost::WorkerInstance& instance) {
+ // Worker can be fired off if *any* parent has room.
+ const WorkerDocumentSet::DocumentInfoSet& parents =
+ instance.worker_document_set()->documents();
+
+ for (WorkerDocumentSet::DocumentInfoSet::const_iterator parent_iter =
+ parents.begin();
+ parent_iter != parents.end(); ++parent_iter) {
+ bool hit_total_worker_limit = false;
+ if (TabCanCreateWorkerProcess(parent_iter->renderer_id(),
+ parent_iter->render_view_route_id(),
+ &hit_total_worker_limit)) {
+ return true;
+ }
+ // Return false if already at the global worker limit (no need to continue
+ // checking parent tabs).
+ if (hit_total_worker_limit)
+ return false;
+ }
+ // If we've reached here, none of the parent tabs is allowed to create an
+ // instance.
+ return false;
+}
+
+bool WorkerService::TabCanCreateWorkerProcess(int renderer_id,
+ int render_view_route_id,
+ bool* hit_total_worker_limit) {
int total_workers = 0;
int workers_per_tab = 0;
+ *hit_total_worker_limit = false;
for (ChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS);
!iter.Done(); ++iter) {
WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter);
@@ -303,11 +335,11 @@ bool WorkerService::CanCreateWorkerProcess(
worker->instances().begin();
cur_instance != worker->instances().end(); ++cur_instance) {
total_workers++;
- if (total_workers >= kMaxWorkersWhenSeparate)
+ if (total_workers >= kMaxWorkersWhenSeparate) {
+ *hit_total_worker_limit = true;
return false;
- if (cur_instance->renderer_id() == instance.renderer_id() &&
- cur_instance->render_view_route_id() ==
- instance.render_view_route_id()) {
+ }
+ if (cur_instance->RendererIsParent(renderer_id, render_view_route_id)) {
workers_per_tab++;
if (workers_per_tab >= kMaxWorkersPerTabWhenSeparate)
return false;
@@ -355,8 +387,8 @@ void WorkerService::SenderShutdown(IPC::Message::Sender* sender) {
for (WorkerProcessHost::Instances::iterator iter =
pending_shared_workers_.begin();
iter != pending_shared_workers_.end(); ) {
- iter->RemoveAllAssociatedDocuments(sender);
- if (iter->IsDocumentSetEmpty()) {
+ iter->worker_document_set()->RemoveAll(sender);
+ if (iter->worker_document_set()->IsEmpty()) {
iter = pending_shared_workers_.erase(iter);
} else {
++iter;
@@ -461,7 +493,7 @@ WorkerService::CreatePendingInstance(const GURL& url,
// No existing pending worker - create a new one.
WorkerProcessHost::WorkerInstance pending(
- url, true, off_the_record, name, 0, MSG_ROUTING_NONE, MSG_ROUTING_NONE);
+ url, true, off_the_record, name, MSG_ROUTING_NONE);
pending_shared_workers_.push_back(pending);
return &pending_shared_workers_.back();
}
diff --git a/chrome/browser/worker_host/worker_service.h b/chrome/browser/worker_host/worker_service.h
index 5db6eee..eec45a0 100644
--- a/chrome/browser/worker_host/worker_service.h
+++ b/chrome/browser/worker_host/worker_service.h
@@ -30,6 +30,7 @@ class WorkerService : public NotificationObserver {
bool is_shared,
bool is_off_the_record,
const string16& name,
+ unsigned long long document_id,
int renderer_pid,
int render_view_route_id,
IPC::Message::Sender* sender,
@@ -43,6 +44,8 @@ class WorkerService : public NotificationObserver {
const string16& name,
bool off_the_record,
unsigned long long document_id,
+ int renderer_pid,
+ int render_view_route_id,
IPC::Message::Sender* sender,
int sender_route_id,
bool* url_mismatch);
@@ -101,6 +104,12 @@ class WorkerService : public NotificationObserver {
bool CanCreateWorkerProcess(
const WorkerProcessHost::WorkerInstance& instance);
+ // Checks if the tab associated with the passed RenderView can create a
+ // worker process based on the process limit when we're using a strategy of
+ // one worker per process.
+ bool TabCanCreateWorkerProcess(
+ int renderer_id, int render_view_route_id, bool* hit_total_worker_limit);
+
// NotificationObserver interface.
void Observe(NotificationType type,
const NotificationSource& source,
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 4c52ea0..7676b1c 100755
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1951,6 +1951,8 @@
'browser/window_sizer_win.cc',
'browser/worker_host/message_port_dispatcher.cc',
'browser/worker_host/message_port_dispatcher.h',
+ 'browser/worker_host/worker_document_set.cc',
+ 'browser/worker_host/worker_document_set.h',
'browser/worker_host/worker_process_host.cc',
'browser/worker_host/worker_process_host.h',
'browser/worker_host/worker_service.cc',
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h
index 24e1e72..ebc7af4 100644
--- a/chrome/common/render_messages.h
+++ b/chrome/common/render_messages.h
@@ -534,6 +534,24 @@ struct ViewMsg_ExecuteCode_Params {
bool all_frames;
};
+// Parameters for the message that creates a worker thread.
+struct ViewHostMsg_CreateWorker_Params {
+ // URL for the worker script.
+ GURL url;
+
+ // True if this is a SharedWorker, false if it is a dedicated Worker.
+ bool is_shared;
+
+ // Name for a SharedWorker, otherwise empty string.
+ string16 name;
+
+ // The ID of the parent document (unique within parent renderer).
+ unsigned long long document_id;
+
+ // RenderView routing id used to send messages back to the parent.
+ int render_view_route_id;
+};
+
// Creates a new view via a control message since the view doesn't yet exist.
struct ViewMsg_New_Params {
// The parent window's id.
@@ -2310,6 +2328,40 @@ struct ParamTraits<ViewMsg_DOMStorageEvent_Params> {
}
};
+// Traits for ViewHostMsg_CreateWorker_Params
+template <>
+struct ParamTraits<ViewHostMsg_CreateWorker_Params> {
+ typedef ViewHostMsg_CreateWorker_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.url);
+ WriteParam(m, p.is_shared);
+ WriteParam(m, p.name);
+ WriteParam(m, p.document_id);
+ WriteParam(m, p.render_view_route_id);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->url) &&
+ ReadParam(m, iter, &p->is_shared) &&
+ ReadParam(m, iter, &p->name) &&
+ ReadParam(m, iter, &p->document_id) &&
+ ReadParam(m, iter, &p->render_view_route_id);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.url, l);
+ l->append(L", ");
+ LogParam(p.is_shared, l);
+ l->append(L", ");
+ LogParam(p.name, l);
+ l->append(L", ");
+ LogParam(p.document_id, l);
+ l->append(L", ");
+ LogParam(p.render_view_route_id, l);
+ l->append(L")");
+ }
+};
+
// Traits for WebCookie
template <>
struct ParamTraits<webkit_glue::WebCookie> {
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index 19d6fae..22f4a0f 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -1754,11 +1754,8 @@ IPC_BEGIN_MESSAGES(ViewHost)
// A renderer sends this to the browser process when it wants to create a
// worker. The browser will create the worker process if necessary, and
// will return the route id on success. On error returns MSG_ROUTING_NONE.
- IPC_SYNC_MESSAGE_CONTROL4_1(ViewHostMsg_CreateWorker,
- GURL /* url */,
- bool /* is_shared */,
- string16 /* name */,
- int /* render_view_route_id */,
+ IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_CreateWorker,
+ ViewHostMsg_CreateWorker_Params,
int /* route_id */)
// This message is sent to the browser to see if an instance of this shared
@@ -1768,10 +1765,11 @@ IPC_BEGIN_MESSAGES(ViewHost)
// the existing worker. If a matching worker is found, the passed-in
// document_id is associated with that worker, to ensure that the worker
// stays alive until the document is detached.
- IPC_SYNC_MESSAGE_CONTROL3_2(ViewHostMsg_LookupSharedWorker,
+ IPC_SYNC_MESSAGE_CONTROL4_2(ViewHostMsg_LookupSharedWorker,
GURL /* url */,
string16 /* name */,
unsigned long long /* document_id */,
+ int /* render_view_route_id */,
int /* route_id */,
bool /* url_mismatch */)
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 8a718db..4c74a61 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -1925,11 +1925,12 @@ WebSharedWorker* RenderView::createSharedWorker(
int route_id = MSG_ROUTING_NONE;
bool url_mismatch = false;
Send(new ViewHostMsg_LookupSharedWorker(
- url, name, document_id, &route_id, &url_mismatch));
+ url, name, document_id, routing_id_, &route_id, &url_mismatch));
if (url_mismatch) {
return NULL;
} else {
return new WebSharedWorkerProxy(RenderThread::current(),
+ document_id,
route_id,
routing_id_);
}
diff --git a/chrome/renderer/websharedworker_proxy.cc b/chrome/renderer/websharedworker_proxy.cc
index 1d5425f..c6741c1 100644
--- a/chrome/renderer/websharedworker_proxy.cc
+++ b/chrome/renderer/websharedworker_proxy.cc
@@ -10,9 +10,10 @@
#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
WebSharedWorkerProxy::WebSharedWorkerProxy(ChildThread* child_thread,
+ unsigned long long document_id,
int route_id,
int render_view_route_id)
- : WebWorkerBase(child_thread, route_id, render_view_route_id),
+ : WebWorkerBase(child_thread, document_id, route_id, render_view_route_id),
connect_listener_(NULL) {
}
diff --git a/chrome/renderer/websharedworker_proxy.h b/chrome/renderer/websharedworker_proxy.h
index c3143db..4a93ff6 100644
--- a/chrome/renderer/websharedworker_proxy.h
+++ b/chrome/renderer/websharedworker_proxy.h
@@ -22,6 +22,7 @@ class WebSharedWorkerProxy : public WebKit::WebSharedWorker,
public:
// If the worker not loaded yet, route_id == MSG_ROUTING_NONE
WebSharedWorkerProxy(ChildThread* child_thread,
+ unsigned long long document_id,
int route_id,
int render_view_route_id);
diff --git a/chrome/renderer/webworker_base.cc b/chrome/renderer/webworker_base.cc
index e32026c..e78ef64 100644
--- a/chrome/renderer/webworker_base.cc
+++ b/chrome/renderer/webworker_base.cc
@@ -19,11 +19,13 @@ using WebKit::WebWorkerClient;
WebWorkerBase::WebWorkerBase(
ChildThread* child_thread,
+ unsigned long long document_id,
int route_id,
int render_view_route_id)
: route_id_(route_id),
render_view_route_id_(render_view_route_id),
- child_thread_(child_thread) {
+ child_thread_(child_thread),
+ document_id_(document_id) {
if (route_id_ != MSG_ROUTING_NONE)
child_thread_->AddRoute(route_id_, this);
}
@@ -54,8 +56,14 @@ void WebWorkerBase::CreateWorkerContext(const GURL& script_url,
const string16& user_agent,
const string16& source_code) {
DCHECK(route_id_ == MSG_ROUTING_NONE);
+ ViewHostMsg_CreateWorker_Params params;
+ params.url = script_url;
+ params.is_shared = is_shared;
+ params.name = name;
+ params.document_id = document_id_;
+ params.render_view_route_id = render_view_route_id_;
IPC::Message* create_message = new ViewHostMsg_CreateWorker(
- script_url, is_shared, name, render_view_route_id_, &route_id_);
+ params, &route_id_);
child_thread_->Send(create_message);
if (route_id_ == MSG_ROUTING_NONE)
return;
diff --git a/chrome/renderer/webworker_base.h b/chrome/renderer/webworker_base.h
index fe5becc..6c031c8 100644
--- a/chrome/renderer/webworker_base.h
+++ b/chrome/renderer/webworker_base.h
@@ -20,6 +20,7 @@ class GURL;
class WebWorkerBase : public IPC::Channel::Listener {
public:
WebWorkerBase(ChildThread* child_thread,
+ unsigned long long document_id,
int route_id,
int render_view_route_id);
@@ -61,6 +62,10 @@ class WebWorkerBase : public IPC::Channel::Listener {
ChildThread* child_thread_;
private:
+ // ID of our parent document (used to shutdown workers when the parent
+ // document is detached).
+ unsigned long long document_id_;
+
// Stores messages that were sent before the StartWorkerContext message.
std::vector<IPC::Message*> queued_messages_;
};
diff --git a/chrome/renderer/webworker_proxy.cc b/chrome/renderer/webworker_proxy.cc
index fdcc9f1..553a3ac 100644
--- a/chrome/renderer/webworker_proxy.cc
+++ b/chrome/renderer/webworker_proxy.cc
@@ -22,8 +22,10 @@ WebWorkerProxy::WebWorkerProxy(
WebWorkerClient* client,
ChildThread* child_thread,
int render_view_route_id)
- : WebWorkerBase(child_thread, MSG_ROUTING_NONE, render_view_route_id),
+ : WebWorkerBase(child_thread, 0, MSG_ROUTING_NONE, render_view_route_id),
client_(client) {
+ // TODO(atwilson): Change to pass in a real document_id when we support nested
+ // workers.
}
WebWorkerProxy::~WebWorkerProxy() {
diff --git a/chrome/test/data/workers/shared_worker_auth.html b/chrome/test/data/workers/shared_worker_auth.html
new file mode 100644
index 0000000..fbe4ad2
--- /dev/null
+++ b/chrome/test/data/workers/shared_worker_auth.html
@@ -0,0 +1,18 @@
+<html>
+
+<head>
+<title>SharedWorker HTTP Auth Test</title>
+
+<script src="worker_utils.js"></script>
+
+<script>
+
+var worker = new SharedWorker("worker_common.js");
+worker.port.postMessage("auth");
+</script>
+</head>
+
+<body>
+<div id=statusPanel></div>
+</body>
+</html>
diff --git a/chrome/test/data/workers/worker_auth.html b/chrome/test/data/workers/worker_auth.html
new file mode 100644
index 0000000..e452155
--- /dev/null
+++ b/chrome/test/data/workers/worker_auth.html
@@ -0,0 +1,18 @@
+<html>
+
+<head>
+<title>Worker HTTP Auth Test</title>
+
+<script src="worker_utils.js"></script>
+
+<script>
+
+var worker = getWorker("worker_common.js");
+worker.postMessage("auth");
+</script>
+</head>
+
+<body>
+<div id=statusPanel></div>
+</body>
+</html>
diff --git a/chrome/test/data/workers/worker_common.js b/chrome/test/data/workers/worker_common.js
index 8caa622..664da58 100644
--- a/chrome/test/data/workers/worker_common.js
+++ b/chrome/test/data/workers/worker_common.js
@@ -12,6 +12,8 @@ if (!self.postMessage) {
onmessage = function(evt) {
if (evt.data == "ping")
postMessage("pong");
+ else if (evt.data == "auth")
+ importScripts("/auth-basic");
else if (/eval.+/.test(evt.data)) {
try {
postMessage(eval(evt.data.substr(5)));
diff --git a/chrome/worker/worker_uitest.cc b/chrome/worker/worker_uitest.cc
index aafad3c..ced60bf 100644
--- a/chrome/worker/worker_uitest.cc
+++ b/chrome/worker/worker_uitest.cc
@@ -9,6 +9,7 @@
#include "chrome/test/automation/browser_proxy.h"
#include "chrome/test/automation/tab_proxy.h"
#include "chrome/test/ui/ui_layout_test.h"
+#include "net/url_request/url_request_unittest.h"
static const char kTestCompleteCookie[] = "status";
static const char kTestCompleteSuccess[] = "OK";
@@ -136,6 +137,15 @@ class WorkerTest : public UILayoutTest {
GURL about_url(std::string("file://localhost/"));
EXPECT_EQ(AUTOMATION_MSG_NAVIGATION_SUCCESS, tab->NavigateToURL(about_url));
}
+
+ bool NavigateAndWaitForAuth(TabProxy* tab, const GURL& url) {
+ // Pass a large number of navigations to tell the tab to block until an auth
+ // dialog pops up.
+ bool timeout = false;
+ tab->NavigateToURLWithTimeout(url, 100, kTestWaitTimeoutMs, &timeout);
+ EXPECT_FALSE(timeout);
+ return tab->NeedsAuth();
+ }
};
@@ -173,6 +183,32 @@ TEST_F(WorkerTest, IncognitoSharedWorkers) {
RunIncognitoTest(L"incognito_worker.html");
}
+const wchar_t kDocRoot[] = L"chrome/test/data/workers";
+
+// Make sure that auth dialog is displayed from worker context.
+TEST_F(WorkerTest, WorkerHttpAuth) {
+ scoped_refptr<HTTPTestServer> server =
+ HTTPTestServer::CreateServer(kDocRoot, NULL);
+
+ ASSERT_TRUE(NULL != server.get());
+ scoped_refptr<TabProxy> tab(GetActiveTab());
+ GURL url = server->TestServerPage("files/worker_auth.html");
+ EXPECT_TRUE(NavigateAndWaitForAuth(tab, url));
+}
+
+// Make sure that auth dialog is displayed from shared worker context.
+TEST_F(WorkerTest, SharedWorkerHttpAuth) {
+ scoped_refptr<HTTPTestServer> server =
+ HTTPTestServer::CreateServer(kDocRoot, NULL);
+ ASSERT_TRUE(NULL != server.get());
+ scoped_refptr<TabProxy> tab(GetActiveTab());
+ EXPECT_EQ(1, GetTabCount());
+ GURL url = server->TestServerPage("files/shared_worker_auth.html");
+ EXPECT_TRUE(NavigateAndWaitForAuth(tab, url));
+ // TODO(atwilson): Add support to automation framework to test for auth
+ // dialogs displayed by non-navigating tabs.
+}
+
#if defined(OS_LINUX)
// Crashes on Linux - http://crbug.com/22898
#define WorkerFastLayoutTests0 DISABLED_WorkerFastLayoutTests0
diff --git a/tools/valgrind/memcheck/suppressions.txt b/tools/valgrind/memcheck/suppressions.txt
index da9c45b..f916499 100644
--- a/tools/valgrind/memcheck/suppressions.txt
+++ b/tools/valgrind/memcheck/suppressions.txt
@@ -1046,9 +1046,9 @@
Memcheck:Leak
fun:_Znw*
...
- fun:_ZN13WorkerService12CreateWorkerERK4GURLbbRKSbItN4base20string16_char_traitsESaItEEiiPN3IPC7Message6SenderEi
- fun:_ZN21ResourceMessageFilter14OnCreateWorkerERK4GURLbRKSbItN4base20string16_char_traitsESaItEEiPi
- fun:_Z16DispatchToMethodI21ResourceMessageFilterMS0_FvRK4GURLbRKSbItN4base20string16_char_traitsESaItEEiPiES1_bS7_iiEvPT_T0_RK6Tuple4IT1_T2_T3_T4_EP6Tuple1IT5_E
+ fun:_ZN13WorkerService12CreateWorker*
+ fun:_ZN21ResourceMessageFilter14OnCreateWorker*
+ fun:_Z16DispatchToMethodI21ResourceMessageFilter*
}
{
bug_22932