summaryrefslogtreecommitdiffstats
path: root/chrome/browser/renderer_host
diff options
context:
space:
mode:
authorKristian Monsen <kristianm@google.com>2010-10-27 13:27:14 +0100
committerKristian Monsen <kristianm@google.com>2010-10-27 13:27:14 +0100
commitbda42a81ee5f9b20d2bebedcf0bbef1e30e5b293 (patch)
treee6c803134a90c4535df4b3d8d1c1d8f03405e462 /chrome/browser/renderer_host
parent026dcf071380a81f0213473bab11c7db9f367bce (diff)
downloadexternal_chromium-bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293.zip
external_chromium-bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293.tar.gz
external_chromium-bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293.tar.bz2
Adding missing files to chrome/browser
These are not used, but added to easier sync with chromium Change-Id: I54e6f2f49677e29736fd502758a438b2e3d685d8
Diffstat (limited to 'chrome/browser/renderer_host')
-rw-r--r--chrome/browser/renderer_host/blob_dispatcher_host.cc88
-rw-r--r--chrome/browser/renderer_host/blob_dispatcher_host.h49
-rw-r--r--chrome/browser/renderer_host/redirect_to_file_resource_handler.cc222
-rw-r--r--chrome/browser/renderer_host/redirect_to_file_resource_handler.h89
-rw-r--r--chrome/browser/renderer_host/render_widget_fullscreen_host.cc10
-rw-r--r--chrome/browser/renderer_host/render_widget_fullscreen_host.h15
-rw-r--r--chrome/browser/renderer_host/test/renderer_accessibility_browsertest.cc142
7 files changed, 615 insertions, 0 deletions
diff --git a/chrome/browser/renderer_host/blob_dispatcher_host.cc b/chrome/browser/renderer_host/blob_dispatcher_host.cc
new file mode 100644
index 0000000..8fdafe5
--- /dev/null
+++ b/chrome/browser/renderer_host/blob_dispatcher_host.cc
@@ -0,0 +1,88 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/renderer_host/blob_dispatcher_host.h"
+
+#include "chrome/browser/child_process_security_policy.h"
+#include "chrome/browser/chrome_blob_storage_context.h"
+#include "chrome/browser/chrome_thread.h"
+#include "chrome/common/render_messages.h"
+#include "googleurl/src/gurl.h"
+#include "ipc/ipc_message.h"
+#include "webkit/blob/blob_data.h"
+#include "webkit/blob/blob_storage_controller.h"
+
+BlobDispatcherHost::BlobDispatcherHost(
+ int process_id,
+ ChromeBlobStorageContext* blob_storage_context)
+ : process_id_(process_id),
+ blob_storage_context_(blob_storage_context) {
+}
+
+BlobDispatcherHost::~BlobDispatcherHost() {
+}
+
+void BlobDispatcherHost::Shutdown() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+
+ // Unregister all the blob URLs that are previously registered in this
+ // process.
+ for (base::hash_set<std::string>::const_iterator iter = blob_urls_.begin();
+ iter != blob_urls_.end(); ++iter) {
+ blob_storage_context_->controller()->UnregisterBlobUrl(GURL(*iter));
+ }
+}
+
+bool BlobDispatcherHost::OnMessageReceived(const IPC::Message& message,
+ bool* msg_is_ok) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+
+ *msg_is_ok = true;
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP_EX(BlobDispatcherHost, message, *msg_is_ok)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_RegisterBlobUrl, OnRegisterBlobUrl)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_RegisterBlobUrlFrom, OnRegisterBlobUrlFrom)
+ IPC_MESSAGE_HANDLER(ViewHostMsg_UnregisterBlobUrl, OnUnregisterBlobUrl)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+// Check if the child process has been granted permission to register the files.
+bool BlobDispatcherHost::CheckPermission(
+ webkit_blob::BlobData* blob_data) const {
+ ChildProcessSecurityPolicy* policy =
+ ChildProcessSecurityPolicy::GetInstance();
+ for (std::vector<webkit_blob::BlobData::Item>::const_iterator iter =
+ blob_data->items().begin();
+ iter != blob_data->items().end(); ++iter) {
+ if (iter->type() == webkit_blob::BlobData::TYPE_FILE) {
+ if (!policy->CanReadFile(process_id_, iter->file_path()))
+ return false;
+ }
+ }
+ return true;
+}
+
+void BlobDispatcherHost::OnRegisterBlobUrl(
+ const GURL& url, const scoped_refptr<webkit_blob::BlobData>& blob_data) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ if (!CheckPermission(blob_data.get()))
+ return;
+ blob_storage_context_->controller()->RegisterBlobUrl(url, blob_data);
+ blob_urls_.insert(url.spec());
+}
+
+void BlobDispatcherHost::OnRegisterBlobUrlFrom(
+ const GURL& url, const GURL& src_url) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ blob_storage_context_->controller()->RegisterBlobUrlFrom(url, src_url);
+ blob_urls_.insert(src_url.spec());
+}
+
+void BlobDispatcherHost::OnUnregisterBlobUrl(const GURL& url) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
+ blob_storage_context_->controller()->UnregisterBlobUrl(url);
+ blob_urls_.erase(url.spec());
+}
diff --git a/chrome/browser/renderer_host/blob_dispatcher_host.h b/chrome/browser/renderer_host/blob_dispatcher_host.h
new file mode 100644
index 0000000..8ba95ff
--- /dev/null
+++ b/chrome/browser/renderer_host/blob_dispatcher_host.h
@@ -0,0 +1,49 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_RENDERER_HOST_BLOB_DISPATCHER_HOST_H_
+#define CHROME_BROWSER_RENDERER_HOST_BLOB_DISPATCHER_HOST_H_
+
+#include "base/hash_tables.h"
+#include "base/ref_counted.h"
+
+class ChromeBlobStorageContext;
+class GURL;
+
+namespace IPC {
+class Message;
+}
+
+namespace webkit_blob {
+class BlobData;
+}
+
+class BlobDispatcherHost {
+ public:
+ BlobDispatcherHost(int process_id,
+ ChromeBlobStorageContext* blob_storage_context);
+ ~BlobDispatcherHost();
+
+ void Shutdown();
+ bool OnMessageReceived(const IPC::Message& message, bool* msg_is_ok);
+
+ private:
+ void OnRegisterBlobUrl(const GURL& url,
+ const scoped_refptr<webkit_blob::BlobData>& blob_data);
+ void OnRegisterBlobUrlFrom(const GURL& url, const GURL& src_url);
+ void OnUnregisterBlobUrl(const GURL& url);
+
+ bool CheckPermission(webkit_blob::BlobData* blob_data) const;
+
+ int process_id_;
+ scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
+
+ // Keep track of blob URLs registered in this process. Need to unregister
+ // all of them when the renderer process dies.
+ base::hash_set<std::string> blob_urls_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(BlobDispatcherHost);
+};
+
+#endif // CHROME_BROWSER_RENDERER_HOST_BLOB_DISPATCHER_HOST_H_
diff --git a/chrome/browser/renderer_host/redirect_to_file_resource_handler.cc b/chrome/browser/renderer_host/redirect_to_file_resource_handler.cc
new file mode 100644
index 0000000..94a5c77
--- /dev/null
+++ b/chrome/browser/renderer_host/redirect_to_file_resource_handler.cc
@@ -0,0 +1,222 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/renderer_host/redirect_to_file_resource_handler.h"
+
+#include "base/file_util.h"
+#include "base/file_util_proxy.h"
+#include "base/logging.h"
+#include "base/platform_file.h"
+#include "base/task.h"
+#include "chrome/browser/child_process_security_policy.h"
+#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
+#include "chrome/common/resource_response.h"
+#include "net/base/file_stream.h"
+#include "net/base/io_buffer.h"
+#include "net/base/mime_sniffer.h"
+#include "net/base/net_errors.h"
+#include "webkit/blob/deletable_file_reference.h"
+
+using webkit_blob::DeletableFileReference;
+
+// TODO(darin): Use the buffer sizing algorithm from AsyncResourceHandler.
+static const int kReadBufSize = 32768;
+
+RedirectToFileResourceHandler::RedirectToFileResourceHandler(
+ ResourceHandler* next_handler,
+ int process_id,
+ ResourceDispatcherHost* host)
+ : callback_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
+ host_(host),
+ next_handler_(next_handler),
+ process_id_(process_id),
+ request_id_(-1),
+ buf_(new net::GrowableIOBuffer()),
+ buf_write_pending_(false),
+ write_cursor_(0),
+ write_callback_(ALLOW_THIS_IN_INITIALIZER_LIST(this),
+ &RedirectToFileResourceHandler::DidWriteToFile),
+ write_callback_pending_(false) {
+}
+
+bool RedirectToFileResourceHandler::OnUploadProgress(int request_id,
+ uint64 position,
+ uint64 size) {
+ return next_handler_->OnUploadProgress(request_id, position, size);
+}
+
+bool RedirectToFileResourceHandler::OnRequestRedirected(
+ int request_id,
+ const GURL& new_url,
+ ResourceResponse* response,
+ bool* defer) {
+ return next_handler_->OnRequestRedirected(request_id, new_url, response,
+ defer);
+}
+
+bool RedirectToFileResourceHandler::OnResponseStarted(
+ int request_id,
+ ResourceResponse* response) {
+ if (response->response_head.status.is_success()) {
+ DCHECK(deletable_file_ && !deletable_file_->path().empty());
+ response->response_head.download_file_path = deletable_file_->path();
+ }
+ return next_handler_->OnResponseStarted(request_id, response);
+}
+
+bool RedirectToFileResourceHandler::OnWillStart(int request_id,
+ const GURL& url,
+ bool* defer) {
+ request_id_ = request_id;
+ if (!deletable_file_) {
+ // Defer starting the request until we have created the temporary file.
+ // TODO(darin): This is sub-optimal. We should not delay starting the
+ // network request like this.
+ *defer = true;
+ base::FileUtilProxy::CreateTemporary(
+ ChromeThread::GetMessageLoopProxyForThread(ChromeThread::FILE),
+ callback_factory_.NewCallback(
+ &RedirectToFileResourceHandler::DidCreateTemporaryFile));
+ return true;
+ }
+ return next_handler_->OnWillStart(request_id, url, defer);
+}
+
+bool RedirectToFileResourceHandler::OnWillRead(int request_id,
+ net::IOBuffer** buf,
+ int* buf_size,
+ int min_size) {
+ DCHECK(min_size == -1);
+
+ if (!buf_->capacity())
+ buf_->SetCapacity(kReadBufSize);
+
+ // We should have paused this network request already if the buffer is full.
+ DCHECK(!BufIsFull());
+
+ *buf = buf_;
+ *buf_size = buf_->RemainingCapacity();
+
+ buf_write_pending_ = true;
+ return true;
+}
+
+bool RedirectToFileResourceHandler::OnReadCompleted(int request_id,
+ int* bytes_read) {
+ if (!buf_write_pending_) {
+ // Ignore spurious OnReadCompleted! PauseRequest(true) called from within
+ // OnReadCompleted tells the ResourceDispatcherHost that we did not consume
+ // the data. PauseRequest(false) then repeats the last OnReadCompleted
+ // call. We pause the request so that we can copy our buffer to disk, so
+ // we need to consume the data now. The ResourceDispatcherHost pause
+ // mechanism does not fit our use case very well.
+ // TODO(darin): Fix the ResourceDispatcherHost to avoid this hack!
+ return true;
+ }
+
+ buf_write_pending_ = false;
+
+ // We use the buffer's offset field to record the end of the buffer.
+
+ int new_offset = buf_->offset() + *bytes_read;
+ DCHECK(new_offset <= buf_->capacity());
+ buf_->set_offset(new_offset);
+
+ if (BufIsFull())
+ host_->PauseRequest(process_id_, request_id, true);
+
+ if (*bytes_read > 0)
+ next_handler_->OnDataDownloaded(request_id, *bytes_read);
+
+ return WriteMore();
+}
+
+bool RedirectToFileResourceHandler::OnResponseCompleted(
+ int request_id,
+ const URLRequestStatus& status,
+ const std::string& security_info) {
+ return next_handler_->OnResponseCompleted(request_id, status, security_info);
+}
+
+void RedirectToFileResourceHandler::OnRequestClosed() {
+ // We require this explicit call to Close since file_stream_ was constructed
+ // directly from a PlatformFile.
+ file_stream_->Close();
+ file_stream_.reset();
+ deletable_file_ = NULL;
+
+ next_handler_->OnRequestClosed();
+}
+
+RedirectToFileResourceHandler::~RedirectToFileResourceHandler() {
+ DCHECK(!file_stream_.get());
+}
+
+void RedirectToFileResourceHandler::DidCreateTemporaryFile(
+ base::PlatformFileError /*error_code*/,
+ base::PassPlatformFile file_handle,
+ FilePath file_path) {
+ deletable_file_ = DeletableFileReference::GetOrCreate(
+ file_path,
+ ChromeThread::GetMessageLoopProxyForThread(ChromeThread::FILE));
+ file_stream_.reset(new net::FileStream(file_handle.ReleaseValue(),
+ base::PLATFORM_FILE_WRITE |
+ base::PLATFORM_FILE_ASYNC));
+ host_->RegisterDownloadedTempFile(
+ process_id_, request_id_, deletable_file_.get());
+ host_->StartDeferredRequest(process_id_, request_id_);
+}
+
+void RedirectToFileResourceHandler::DidWriteToFile(int result) {
+ write_callback_pending_ = false;
+
+ bool failed = false;
+ if (result > 0) {
+ write_cursor_ += result;
+ failed = !WriteMore();
+ } else {
+ failed = true;
+ }
+
+ if (failed)
+ host_->CancelRequest(process_id_, request_id_, false);
+}
+
+bool RedirectToFileResourceHandler::WriteMore() {
+ DCHECK(file_stream_.get());
+ for (;;) {
+ if (write_cursor_ == buf_->offset()) {
+ // We've caught up to the network load, but it may be in the process of
+ // appending more data to the buffer.
+ if (!buf_write_pending_) {
+ if (BufIsFull())
+ host_->PauseRequest(process_id_, request_id_, false);
+ buf_->set_offset(0);
+ write_cursor_ = 0;
+ }
+ return true;
+ }
+ if (write_callback_pending_)
+ return true;
+ DCHECK(write_cursor_ < buf_->offset());
+ int rv = file_stream_->Write(buf_->StartOfBuffer() + write_cursor_,
+ buf_->offset() - write_cursor_,
+ &write_callback_);
+ if (rv == net::ERR_IO_PENDING) {
+ write_callback_pending_ = true;
+ return true;
+ }
+ if (rv < 0)
+ return false;
+ write_cursor_ += rv;
+ }
+}
+
+bool RedirectToFileResourceHandler::BufIsFull() const {
+ // This is a hack to workaround BufferedResourceHandler's inability to
+ // deal with a ResourceHandler that returns a buffer size of less than
+ // 2 * net::kMaxBytesToSniff from its OnWillRead method.
+ // TODO(darin): Fix this retardation!
+ return buf_->RemainingCapacity() <= (2 * net::kMaxBytesToSniff);
+}
diff --git a/chrome/browser/renderer_host/redirect_to_file_resource_handler.h b/chrome/browser/renderer_host/redirect_to_file_resource_handler.h
new file mode 100644
index 0000000..4929711
--- /dev/null
+++ b/chrome/browser/renderer_host/redirect_to_file_resource_handler.h
@@ -0,0 +1,89 @@
+// Copyright (c) 2006-2008 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_RENDERER_HOST_REDIRECT_TO_FILE_RESOURCE_HANDLER_H_
+#define CHROME_BROWSER_RENDERER_HOST_REDIRECT_TO_FILE_RESOURCE_HANDLER_H_
+
+#include "base/file_path.h"
+#include "base/platform_file.h"
+#include "base/ref_counted.h"
+#include "base/scoped_callback_factory.h"
+#include "base/scoped_ptr.h"
+#include "chrome/browser/renderer_host/resource_handler.h"
+#include "net/base/completion_callback.h"
+
+class RefCountedPlatformFile;
+class ResourceDispatcherHost;
+
+namespace net {
+class FileStream;
+class GrowableIOBuffer;
+}
+
+namespace webkit_blob {
+class DeletableFileReference;
+}
+
+// Redirects network data to a file. This is intended to be layered in front
+// of either the AsyncResourceHandler or the SyncResourceHandler.
+class RedirectToFileResourceHandler : public ResourceHandler {
+ public:
+ RedirectToFileResourceHandler(
+ ResourceHandler* next_handler,
+ int process_id,
+ ResourceDispatcherHost* resource_dispatcher_host);
+
+ // ResourceHandler implementation:
+ bool OnUploadProgress(int request_id, uint64 position, uint64 size);
+ bool OnRequestRedirected(int request_id, const GURL& new_url,
+ ResourceResponse* response, bool* defer);
+ bool OnResponseStarted(int request_id, ResourceResponse* response);
+ bool OnWillStart(int request_id, const GURL& url, bool* defer);
+ bool OnWillRead(int request_id, net::IOBuffer** buf, int* buf_size,
+ int min_size);
+ bool OnReadCompleted(int request_id, int* bytes_read);
+ bool OnResponseCompleted(int request_id,
+ const URLRequestStatus& status,
+ const std::string& security_info);
+ void OnRequestClosed();
+
+ private:
+ virtual ~RedirectToFileResourceHandler();
+ void DidCreateTemporaryFile(base::PlatformFileError error_code,
+ base::PassPlatformFile file_handle,
+ FilePath file_path);
+ void DidWriteToFile(int result);
+ bool WriteMore();
+ bool BufIsFull() const;
+
+ base::ScopedCallbackFactory<RedirectToFileResourceHandler> callback_factory_;
+
+ ResourceDispatcherHost* host_;
+ scoped_refptr<ResourceHandler> next_handler_;
+ int process_id_;
+ int request_id_;
+
+ // We allocate a single, fixed-size IO buffer (buf_) used to read from the
+ // network (buf_write_pending_ is true while the system is copying data into
+ // buf_), and then write this buffer out to disk (write_callback_pending_ is
+ // true while writing to disk). Reading from the network is suspended while
+ // the buffer is full (BufIsFull returns true). The write_cursor_ member
+ // tracks the offset into buf_ that we are writing to disk.
+
+ scoped_refptr<net::GrowableIOBuffer> buf_;
+ bool buf_write_pending_;
+ int write_cursor_;
+
+ scoped_ptr<net::FileStream> file_stream_;
+ net::CompletionCallbackImpl<RedirectToFileResourceHandler> write_callback_;
+ bool write_callback_pending_;
+
+ // We create a DeletableFileReference for the temp file created as
+ // a result of the download.
+ scoped_refptr<webkit_blob::DeletableFileReference> deletable_file_;
+
+ DISALLOW_COPY_AND_ASSIGN(RedirectToFileResourceHandler);
+};
+
+#endif // CHROME_BROWSER_RENDERER_HOST_REDIRECT_TO_FILE_RESOURCE_HANDLER_H_
diff --git a/chrome/browser/renderer_host/render_widget_fullscreen_host.cc b/chrome/browser/renderer_host/render_widget_fullscreen_host.cc
new file mode 100644
index 0000000..c3ee786
--- /dev/null
+++ b/chrome/browser/renderer_host/render_widget_fullscreen_host.cc
@@ -0,0 +1,10 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/renderer_host/render_widget_fullscreen_host.h"
+
+RenderWidgetFullscreenHost::RenderWidgetFullscreenHost(
+ RenderProcessHost* process, int routing_id)
+ : RenderWidgetHost(process, routing_id) {
+}
diff --git a/chrome/browser/renderer_host/render_widget_fullscreen_host.h b/chrome/browser/renderer_host/render_widget_fullscreen_host.h
new file mode 100644
index 0000000..1906b4b
--- /dev/null
+++ b/chrome/browser/renderer_host/render_widget_fullscreen_host.h
@@ -0,0 +1,15 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_RENDERER_HOST_RENDER_WIDGET_FULLSCREEN_HOST_H_
+#define CHROME_BROWSER_RENDERER_HOST_RENDER_WIDGET_FULLSCREEN_HOST_H_
+
+#include "chrome/browser/renderer_host/render_widget_host.h"
+
+class RenderWidgetFullscreenHost : public RenderWidgetHost {
+ public:
+ RenderWidgetFullscreenHost(RenderProcessHost* process, int routing_id);
+};
+
+#endif // CHROME_BROWSER_RENDERER_HOST_RENDER_WIDGET_FULLSCREEN_HOST_H_
diff --git a/chrome/browser/renderer_host/test/renderer_accessibility_browsertest.cc b/chrome/browser/renderer_host/test/renderer_accessibility_browsertest.cc
new file mode 100644
index 0000000..b12c6a7
--- /dev/null
+++ b/chrome/browser/renderer_host/test/renderer_accessibility_browsertest.cc
@@ -0,0 +1,142 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+#include <vector>
+
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/browser.h"
+#include "chrome/browser/browser_window.h"
+#include "chrome/browser/renderer_host/render_view_host.h"
+#include "chrome/browser/renderer_host/render_widget_host.h"
+#include "chrome/browser/renderer_host/render_widget_host_view.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/common/render_messages.h"
+#include "chrome/common/notification_type.h"
+#include "chrome/test/in_process_browser_test.h"
+#include "chrome/test/ui_test_utils.h"
+
+#if defined(OS_WIN)
+#include <atlbase.h>
+#include <atlcom.h>
+#endif
+
+using webkit_glue::WebAccessibility;
+
+namespace {
+
+class RendererAccessibilityBrowserTest : public InProcessBrowserTest {
+ public:
+ RendererAccessibilityBrowserTest() {}
+
+ // InProcessBrowserTest
+ void SetUpInProcessBrowserTestFixture();
+ void TearDownInProcessBrowserTestFixture();
+
+ protected:
+ std::string GetAttr(const WebAccessibility& node,
+ const WebAccessibility::Attribute attr);
+};
+
+void RendererAccessibilityBrowserTest::SetUpInProcessBrowserTestFixture() {
+#if defined(OS_WIN)
+ // ATL needs a pointer to a COM module.
+ static CComModule module;
+ _pAtlModule = &module;
+
+ // Make sure COM is initialized for this thread; it's safe to call twice.
+ ::CoInitialize(NULL);
+#endif
+}
+
+void RendererAccessibilityBrowserTest::TearDownInProcessBrowserTestFixture() {
+#if defined(OS_WIN)
+ ::CoUninitialize();
+#endif
+}
+// Convenience method to get the value of a particular WebAccessibility
+// node attribute as a UTF-8 const char*.
+std::string RendererAccessibilityBrowserTest::GetAttr(
+ const WebAccessibility& node, const WebAccessibility::Attribute attr) {
+ std::map<int32, string16>::const_iterator iter = node.attributes.find(attr);
+ if (iter != node.attributes.end())
+ return UTF16ToUTF8(iter->second);
+ else
+ return "";
+}
+
+IN_PROC_BROWSER_TEST_F(RendererAccessibilityBrowserTest,
+ TestCrossPlatformAccessibilityTree) {
+ // Create a data url and load it.
+ const char url_str[] =
+ "data:text/html,"
+ "<!doctype html>"
+ "<html><head><title>Accessibility Test</title></head>"
+ "<body><input type='button' value='push' /><input type='checkbox' />"
+ "</body></html>";
+ GURL url(url_str);
+ browser()->OpenURL(url, GURL(), CURRENT_TAB, PageTransition::TYPED);
+
+ // Tell the renderer to send an accessibility tree, then wait for the
+ // notification that it's been received.
+ RenderWidgetHostView* host_view =
+ browser()->GetSelectedTabContents()->GetRenderWidgetHostView();
+ RenderWidgetHost* host = host_view->GetRenderWidgetHost();
+ RenderViewHost* view_host = static_cast<RenderViewHost*>(host);
+ view_host->set_save_accessibility_tree_for_testing(true);
+ view_host->EnableRendererAccessibility();
+ ui_test_utils::WaitForNotification(
+ NotificationType::RENDER_VIEW_HOST_ACCESSIBILITY_TREE_UPDATED);
+
+ // Check properties of the root element of the tree.
+ const WebAccessibility& tree = view_host->accessibility_tree();
+ EXPECT_STREQ(url_str, GetAttr(tree, WebAccessibility::ATTR_DOC_URL).c_str());
+ EXPECT_STREQ(
+ "Accessibility Test",
+ GetAttr(tree, WebAccessibility::ATTR_DOC_TITLE).c_str());
+ EXPECT_STREQ(
+ "html", GetAttr(tree, WebAccessibility::ATTR_DOC_DOCTYPE).c_str());
+ EXPECT_STREQ(
+ "text/html", GetAttr(tree, WebAccessibility::ATTR_DOC_MIMETYPE).c_str());
+ EXPECT_STREQ("Accessibility Test", UTF16ToUTF8(tree.name).c_str());
+ EXPECT_EQ(WebAccessibility::ROLE_WEB_AREA, tree.role);
+
+ // Check properites of the BODY element.
+ ASSERT_EQ(1U, tree.children.size());
+ const WebAccessibility& body = tree.children[0];
+ EXPECT_EQ(WebAccessibility::ROLE_GROUP, body.role);
+ EXPECT_STREQ("body", GetAttr(body, WebAccessibility::ATTR_HTML_TAG).c_str());
+ EXPECT_STREQ("block", GetAttr(body, WebAccessibility::ATTR_DISPLAY).c_str());
+
+ // Check properties of the two children of the BODY element.
+ ASSERT_EQ(2U, body.children.size());
+
+ const WebAccessibility& button = body.children[0];
+ EXPECT_EQ(WebAccessibility::ROLE_BUTTON, button.role);
+ EXPECT_STREQ(
+ "input", GetAttr(button, WebAccessibility::ATTR_HTML_TAG).c_str());
+ EXPECT_STREQ("push", UTF16ToUTF8(button.name).c_str());
+ EXPECT_STREQ(
+ "inline-block", GetAttr(button, WebAccessibility::ATTR_DISPLAY).c_str());
+ ASSERT_EQ(2U, button.html_attributes.size());
+ EXPECT_STREQ("type", UTF16ToUTF8(button.html_attributes[0].first).c_str());
+ EXPECT_STREQ("button", UTF16ToUTF8(button.html_attributes[0].second).c_str());
+ EXPECT_STREQ("value", UTF16ToUTF8(button.html_attributes[1].first).c_str());
+ EXPECT_STREQ("push", UTF16ToUTF8(button.html_attributes[1].second).c_str());
+
+ const WebAccessibility& checkbox = body.children[1];
+ EXPECT_EQ(WebAccessibility::ROLE_CHECKBOX, checkbox.role);
+ EXPECT_STREQ(
+ "input", GetAttr(checkbox, WebAccessibility::ATTR_HTML_TAG).c_str());
+ EXPECT_STREQ(
+ "inline-block",
+ GetAttr(checkbox, WebAccessibility::ATTR_DISPLAY).c_str());
+ ASSERT_EQ(1U, checkbox.html_attributes.size());
+ EXPECT_STREQ(
+ "type", UTF16ToUTF8(checkbox.html_attributes[0].first).c_str());
+ EXPECT_STREQ(
+ "checkbox", UTF16ToUTF8(checkbox.html_attributes[0].second).c_str());
+}
+
+} // namespace