Implement CONTENT_SETTING_ASK for database.  Also some cleanup of the dialog for local storage.

BUG=34628
TEST=none

Review URL: http://codereview.chromium.org/605028

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@39214 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/cookie_modal_dialog.cc b/chrome/browser/cookie_modal_dialog.cc
index 496843c..325378d 100644
--- a/chrome/browser/cookie_modal_dialog.cc
+++ b/chrome/browser/cookie_modal_dialog.cc
@@ -8,6 +8,7 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/common/pref_service.h"
 
+// Cookies
 CookiePromptModalDialog::CookiePromptModalDialog(
     TabContents* tab_contents,
     const GURL& origin,
@@ -20,7 +21,7 @@
       delegate_(delegate) {
 }
 
-
+// LocalStorage
 CookiePromptModalDialog::CookiePromptModalDialog(
     TabContents* tab_contents,
     const GURL& origin,
@@ -35,6 +36,30 @@
       delegate_(delegate) {
 }
 
+// Database
+CookiePromptModalDialog::CookiePromptModalDialog(
+    TabContents* tab_contents,
+    const GURL& origin,
+    const string16& database_name,
+    CookiePromptModalDialogDelegate* delegate)
+    : AppModalDialog(tab_contents, std::wstring()),
+      dialog_type_(DIALOG_TYPE_DATABASE),
+      origin_(origin),
+      database_name_(database_name),
+      delegate_(delegate) {
+}
+
+void CookiePromptModalDialog::AllowSiteData(bool remember,
+                                            bool session_expire) {
+  delegate_->AllowSiteData(remember, session_expire);
+  delegate_ = NULL;  // It can be deleted at any point now.
+}
+
+void CookiePromptModalDialog::BlockSiteData(bool remember) {
+  delegate_->BlockSiteData(remember);
+  delegate_ = NULL;  // It can be deleted at any point now.
+}
+
 // static
 void CookiePromptModalDialog::RegisterPrefs(PrefService* prefs) {
   prefs->RegisterBooleanPref(prefs::kCookiePromptExpanded, false);
diff --git a/chrome/browser/cookie_modal_dialog.h b/chrome/browser/cookie_modal_dialog.h
index f704bad..6410c32 100644
--- a/chrome/browser/cookie_modal_dialog.h
+++ b/chrome/browser/cookie_modal_dialog.h
@@ -20,8 +20,8 @@
  public:
   enum DialogType {
     DIALOG_TYPE_COOKIE = 0,
-    DIALOG_TYPE_LOCAL_STORAGE
-    // TODO(jorlow): Database
+    DIALOG_TYPE_LOCAL_STORAGE,
+    DIALOG_TYPE_DATABASE
     // TODO(michaeln): AppCache
   };
 
@@ -31,12 +31,15 @@
                           const GURL& origin,
                           const std::string& cookie_line,
                           CookiePromptModalDialogDelegate* delegate);
-  CookiePromptModalDialog(
-      TabContents* tab_contents,
-      const GURL& origin,
-      const string16& key,
-      const string16& value,
-      CookiePromptModalDialogDelegate* delegate);
+  CookiePromptModalDialog(TabContents* tab_contents,
+                          const GURL& origin,
+                          const string16& key,
+                          const string16& value,
+                          CookiePromptModalDialogDelegate* delegate);
+  CookiePromptModalDialog(TabContents* tab_contents,
+                          const GURL& origin,
+                          const string16& database_name,
+                          CookiePromptModalDialogDelegate* delegate);
   virtual ~CookiePromptModalDialog() {}
 
   static void RegisterPrefs(PrefService* prefs);
@@ -51,7 +54,11 @@
   const std::string& cookie_line() const { return cookie_line_; }
   const string16& local_storage_key() const { return local_storage_key_; }
   const string16& local_storage_value() const { return local_storage_value_; }
-  CookiePromptModalDialogDelegate* GetDelegate() { return delegate_; }
+  const string16& database_name() const { return database_name_; }
+
+  // Send a response to our delegate.
+  void AllowSiteData(bool remember, bool session_expire);
+  void BlockSiteData(bool remember);
 
  protected:
   // AppModalDialog overrides.
@@ -73,8 +80,12 @@
   const string16 local_storage_key_;
   const string16 local_storage_value_;
 
+   // Database name.
+  const string16 database_name_;
+
   // Delegate. The caller should provide one in order to receive results
-  // from this delegate.
+  // from this delegate.  Any time after calling one of these methods, the
+  // delegate could be deleted
   CookiePromptModalDialogDelegate* delegate_;
 
   DISALLOW_COPY_AND_ASSIGN(CookiePromptModalDialog);
diff --git a/chrome/browser/cookie_prompt_modal_dialog_delegate.h b/chrome/browser/cookie_prompt_modal_dialog_delegate.h
index 0be9b850..ed21a74 100644
--- a/chrome/browser/cookie_prompt_modal_dialog_delegate.h
+++ b/chrome/browser/cookie_prompt_modal_dialog_delegate.h
@@ -6,6 +6,9 @@
 #define CHROME_BROWSER_COOKIE_PROMPT_MODAL_DIALOG_DELEGATE_H_
 
 // Delegate for handling modal dialog results from CookiePromptModalDialog.
+// The implementer of this MUST guarentee that from the time it's passed to the
+// CookieModalDialog until one of these methods are called it will not be
+// deleted.
 class CookiePromptModalDialogDelegate {
  public:
   // Allow site data to be set. If |remember| is true, record this decision
diff --git a/chrome/browser/in_process_webkit/dom_storage_permission_request.cc b/chrome/browser/in_process_webkit/dom_storage_permission_request.cc
index 6970cc9b..93b21ef 100644
--- a/chrome/browser/in_process_webkit/dom_storage_permission_request.cc
+++ b/chrome/browser/in_process_webkit/dom_storage_permission_request.cc
@@ -24,16 +24,6 @@
   return response_content_setting_;
 }
 
-void DOMStoragePermissionRequest::SendResponse(ContentSetting content_setting,
-                                               bool remember) {
-  response_content_setting_ = content_setting;
-  if (remember) {
-    host_content_settings_map_->SetContentSetting(
-        url_.host(), CONTENT_SETTINGS_TYPE_COOKIES, content_setting);
-  }
-  event_.Signal();
-}
-
 // static
 void DOMStoragePermissionRequest::PromptUser(
     DOMStoragePermissionRequest* dom_storage_permission_request) {
@@ -56,9 +46,6 @@
   }
 
 #if defined(OS_WIN)
-  // TODO(darin): It seems like it would be interesting if the dialog actually
-  // showed the name and value being stored (as is done for cookies).
-  const std::string& host = dom_storage_permission_request->url().host();
   RunLocalStoragePrompt(browser->GetSelectedTabContents(),
                         dom_storage_permission_request->url(),
                         dom_storage_permission_request->key(),
@@ -79,3 +66,13 @@
 void DOMStoragePermissionRequest::BlockSiteData(bool remember) {
   SendResponse(CONTENT_SETTING_BLOCK, remember);
 }
+
+void DOMStoragePermissionRequest::SendResponse(ContentSetting content_setting,
+                                               bool remember) {
+  response_content_setting_ = content_setting;
+  if (remember) {
+    host_content_settings_map_->SetContentSetting(
+        url_.host(), CONTENT_SETTINGS_TYPE_COOKIES, content_setting);
+  }
+  event_.Signal();
+}
diff --git a/chrome/browser/in_process_webkit/dom_storage_permission_request.h b/chrome/browser/in_process_webkit/dom_storage_permission_request.h
index 3d0d81fe..cad41cb4 100644
--- a/chrome/browser/in_process_webkit/dom_storage_permission_request.h
+++ b/chrome/browser/in_process_webkit/dom_storage_permission_request.h
@@ -26,7 +26,6 @@
 
 
   ContentSetting WaitOnResponse();
-  void SendResponse(ContentSetting content_setting, bool remember);
 
   const GURL& url() const { return url_; }
   const string16& key() const { return key_; }
@@ -40,6 +39,8 @@
   virtual void BlockSiteData(bool remember);
 
  private:
+  void SendResponse(ContentSetting content_setting, bool remember);
+
   // The URL we need to get permission for.
   const GURL url_;
 
diff --git a/chrome/browser/message_box_handler.cc b/chrome/browser/message_box_handler.cc
index 4a2d19f..df4820f 100644
--- a/chrome/browser/message_box_handler.cc
+++ b/chrome/browser/message_box_handler.cc
@@ -67,7 +67,6 @@
       new CookiePromptModalDialog(tab_contents, origin, cookie_line, delegate));
 }
 
-
 void RunLocalStoragePrompt(
     TabContents* tab_contents,
     const GURL& origin,
@@ -77,5 +76,15 @@
   Singleton<AppModalDialogQueue>()->AddDialog(
       new CookiePromptModalDialog(tab_contents, origin, key, value, delegate));
 }
+
+void RunDatabasePrompt(
+    TabContents* tab_contents,
+    const GURL& origin,
+    const string16& database_name,
+    CookiePromptModalDialogDelegate* delegate) {
+  Singleton<AppModalDialogQueue>()->AddDialog(
+      new CookiePromptModalDialog(tab_contents, origin, database_name,
+                                  delegate));
+}
 #endif
 
diff --git a/chrome/browser/message_box_handler.h b/chrome/browser/message_box_handler.h
index 7b16c359..9521a0f 100644
--- a/chrome/browser/message_box_handler.h
+++ b/chrome/browser/message_box_handler.h
@@ -59,6 +59,15 @@
     const string16& key,
     const string16& value,
     CookiePromptModalDialogDelegate* delegate);
+
+// This will display a modal dialog box with the database name on every open
+// and ask the user to accept or reject it. The caller should pass |delegate|
+// that will handle the reply from the dialog.
+void RunDatabasePrompt(
+    TabContents* tab_contents,
+    const GURL& origin,
+    const string16& database_name,
+    CookiePromptModalDialogDelegate* delegate);
 #endif
 
 #endif  // CHROME_BROWSER_MESSAGE_BOX_HANDLER_H_
diff --git a/chrome/browser/renderer_host/database_dispatcher_host.cc b/chrome/browser/renderer_host/database_dispatcher_host.cc
index a57244a..e7734ac 100644
--- a/chrome/browser/renderer_host/database_dispatcher_host.cc
+++ b/chrome/browser/renderer_host/database_dispatcher_host.cc
@@ -150,8 +150,13 @@
   scoped_ptr<WebSecurityOrigin> security_origin(
       WebSecurityOrigin::createFromDatabaseIdentifier(origin_identifier));
   string16 origin(security_origin->toString());
+  GURL url = GURL(origin);
 
-  ContentSetting content_setting = GetContentSetting(origin);
+  HostContentSettingsMap* host_content_settings_map = resource_message_filter_->
+      GetRequestContextForURL(url)->host_content_settings_map();
+  ContentSetting content_setting = host_content_settings_map->GetContentSetting(
+      url.host(), CONTENT_SETTINGS_TYPE_COOKIES);
+
   if (content_setting == CONTENT_SETTING_ASK) {
     // Create a task for each possible outcome.
     scoped_ptr<Task> on_allow(NewRunnableMethod(
@@ -161,10 +166,9 @@
         this, &DatabaseDispatcherHost::OnDatabaseOpenFileBlocked, message_id));
     // And then let the permission request object do the rest.
     scoped_refptr<DatabasePermissionRequest> request(
-        new DatabasePermissionRequest(origin,
-                                      database_name,
-                                      on_allow.release(),
-                                      on_block.release()));
+        new DatabasePermissionRequest(url, database_name, on_allow.release(),
+                                      on_block.release(),
+                                      host_content_settings_map));
     request->RequestPermission();
   } else if (content_setting == CONTENT_SETTING_ALLOW) {
     OnDatabaseOpenFileAllowed(vfs_file_name, desired_flags, message_id);
@@ -476,14 +480,3 @@
   SendMessage(new ViewMsg_DatabaseOpenFileResponse(message_id,
                                                    response_params));
 }
-
-ContentSetting DatabaseDispatcherHost::GetContentSetting(
-    const string16& origin) {
-  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
-  GURL url = GURL(origin);
-  std::string host = url.host();
-  ChromeURLRequestContext* url_request_context =
-      resource_message_filter_->GetRequestContextForURL(url);
-  return url_request_context->host_content_settings_map()->GetContentSetting(
-       host, CONTENT_SETTINGS_TYPE_COOKIES);
-}
diff --git a/chrome/browser/renderer_host/database_dispatcher_host.h b/chrome/browser/renderer_host/database_dispatcher_host.h
index e9b3f2b..4c16d0625 100644
--- a/chrome/browser/renderer_host/database_dispatcher_host.h
+++ b/chrome/browser/renderer_host/database_dispatcher_host.h
@@ -93,9 +93,6 @@
                                  int32 message_id);
   void OnDatabaseOpenFileBlocked(int32 message_id);
 
-  // Get the content setting based on an origin.  IO thread only.
-  ContentSetting GetContentSetting(const string16& origin);
-
   // The database tracker for the current profile.
   scoped_refptr<webkit_database::DatabaseTracker> db_tracker_;
 
diff --git a/chrome/browser/renderer_host/database_permission_request.cc b/chrome/browser/renderer_host/database_permission_request.cc
index 73a9977..32fa8e6 100644
--- a/chrome/browser/renderer_host/database_permission_request.cc
+++ b/chrome/browser/renderer_host/database_permission_request.cc
@@ -4,17 +4,23 @@
 
 #include "chrome/browser/renderer_host/database_permission_request.h"
 
+
+#include "chrome/browser/browser_list.h"
 #include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/host_content_settings_map.h"
+#include "chrome/browser/message_box_handler.h"
 
 DatabasePermissionRequest::DatabasePermissionRequest(
-    const string16& origin,
+    const GURL& url,
     const string16& database_name,
     Task* on_allow,
-    Task* on_block)
-    : origin_(origin),
+    Task* on_block,
+    HostContentSettingsMap* settings_map)
+    : url_(url),
       database_name_(database_name),
       on_allow_(on_allow),
-      on_block_(on_block) {
+      on_block_(on_block),
+      host_content_settings_map_(settings_map) {
   DCHECK(on_allow_.get());
   DCHECK(on_block_.get());
 }
@@ -23,16 +29,70 @@
 }
 
 void DatabasePermissionRequest::RequestPermission() {
-  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
-  ChromeThread::PostTask(
-      ChromeThread::UI, FROM_HERE, NewRunnableMethod(
-          this, &DatabasePermissionRequest::RequestPermissionUI));
+  if (ChromeThread::CurrentlyOn(ChromeThread::IO)) {
+    ChromeThread::PostTask(
+        ChromeThread::UI, FROM_HERE, NewRunnableMethod(
+            this, &DatabasePermissionRequest::RequestPermission));
+    return;
+  }
+  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+
+  // Cookie settings may have changed.
+  ContentSetting setting = host_content_settings_map_->GetContentSetting(
+      url_, CONTENT_SETTINGS_TYPE_COOKIES);
+  if (setting != CONTENT_SETTING_ASK) {
+    SendResponse(setting, false);
+    return;
+  }
+
+  Browser* browser = BrowserList::GetLastActive();
+  if (!browser || !browser->GetSelectedTabContents()) {
+    BlockSiteData(false);
+    return;
+  }
+
+#if defined(OS_WIN)
+  self_ref_ = this;
+  // Will call either AllowSiteData or BlockSiteData which will NULL out our
+  // self reference.
+  RunDatabasePrompt(browser->GetSelectedTabContents(), url_,
+                    database_name_, this);
+#else
+  // TODO(jorlow): Enable prompting for other ports.
+  BlockSiteData(false);
+#endif
 }
 
-void DatabasePermissionRequest::RequestPermissionUI() {
-  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
-  bool allow = false;  // TODO(jorlow/darin): Allow user to choose.
+void DatabasePermissionRequest::AllowSiteData(bool remember,
+                                              bool session_expire) {
+  SendResponse(CONTENT_SETTING_ALLOW, remember);
+}
 
-  Task* task = allow ? on_allow_.release() : on_block_.release();
-  ChromeThread::PostTask(ChromeThread::IO, FROM_HERE, task);
+void DatabasePermissionRequest::BlockSiteData(bool remember) {
+  SendResponse(CONTENT_SETTING_BLOCK, remember);
+}
+
+void DatabasePermissionRequest::SendResponse(ContentSetting content_setting,
+                                             bool remember) {
+  if (remember) {
+    host_content_settings_map_->SetContentSetting(
+        url_.host(), CONTENT_SETTINGS_TYPE_COOKIES, content_setting);
+  }
+
+  if (content_setting == CONTENT_SETTING_ALLOW) {
+    ChromeThread::PostTask(ChromeThread::IO, FROM_HERE, on_allow_.release());
+  } else {
+    DCHECK(content_setting == CONTENT_SETTING_BLOCK);
+    ChromeThread::PostTask(ChromeThread::IO, FROM_HERE, on_block_.release());
+  }
+
+  // Release all resources.
+  on_allow_.reset();
+  on_block_.reset();
+
+  // And lastly, release our self ref which may trigger delete.  Do the release
+  // on a local variable instead of a member variable to avoid reentrancy
+  // nastiness if the ref count goes to 0.
+  scoped_refptr<DatabasePermissionRequest> self;
+  self.swap(self_ref_);
 }
diff --git a/chrome/browser/renderer_host/database_permission_request.h b/chrome/browser/renderer_host/database_permission_request.h
index 7760dcd..5cf391c 100644
--- a/chrome/browser/renderer_host/database_permission_request.h
+++ b/chrome/browser/renderer_host/database_permission_request.h
@@ -8,38 +8,51 @@
 #include "base/ref_counted.h"
 #include "base/scoped_ptr.h"
 #include "base/string16.h"
+#include "chrome/browser/cookie_prompt_modal_dialog_delegate.h"
+#include "chrome/common/content_settings.h"
+#include "googleurl/src/gurl.h"
 
+class HostContentSettingsMap;
 class Task;
 
 // This class is fully threadsafe.
 class DatabasePermissionRequest
-    : public base::RefCountedThreadSafe<DatabasePermissionRequest> {
+    : public base::RefCountedThreadSafe<DatabasePermissionRequest>,
+      public CookiePromptModalDialogDelegate {
  public:
-  DatabasePermissionRequest(const string16& origin,
+  DatabasePermissionRequest(const GURL& url,
                             const string16& database_name,
                             Task* on_allow,
-                            Task* on_block);
+                            Task* on_block,
+                            HostContentSettingsMap* settings_map);
   ~DatabasePermissionRequest();
 
-  const string16& origin() const { return origin_; }
+  const GURL& url() const { return url_; }
   const string16& database_name() const { return database_name_; }
 
   // Start the permission request process.
   void RequestPermission();
 
- private:
-  // Called on the UI thread to pop up UI to request permission to open the
-  // database.
-  void RequestPermissionUI();
+  // CookiesPromptViewDelegate methods:
+  virtual void AllowSiteData(bool remember, bool session_expire);
+  virtual void BlockSiteData(bool remember);
 
-  // Info to provide the user while asking for permission.
-  const string16 origin_;
+ private:
+  void SendResponse(ContentSetting content_setting, bool remember);
+
+  // The URL to get permission for.
+  const GURL url_;
   const string16 database_name_;
 
   // Set on IO, possibly release()ed on UI, destroyed on IO or UI.
   scoped_ptr<Task> on_allow_;
   scoped_ptr<Task> on_block_;
 
+  scoped_refptr<HostContentSettingsMap> host_content_settings_map_;
+
+  // Released once we have our answer.
+  scoped_refptr<DatabasePermissionRequest> self_ref_;
+
   DISALLOW_IMPLICIT_CONSTRUCTORS(DatabasePermissionRequest);
 };
 
diff --git a/chrome/browser/views/cookie_prompt_view.cc b/chrome/browser/views/cookie_prompt_view.cc
index 08511143..dcb7a4a 100644
--- a/chrome/browser/views/cookie_prompt_view.cc
+++ b/chrome/browser/views/cookie_prompt_view.cc
@@ -17,6 +17,7 @@
 #include "chrome/browser/profile.h"
 #include "chrome/browser/views/browser_dialogs.h"
 #include "chrome/browser/views/cookie_info_view.h"
+#include "chrome/browser/views/database_open_info_view.h"
 #include "chrome/browser/views/local_storage_set_item_info_view.h"
 #include "chrome/browser/views/options/content_settings_window_view.h"
 #include "chrome/common/pref_names.h"
@@ -92,8 +93,8 @@
 }
 
 void CookiePromptView::WindowClosing() {
-  if (!signaled_ && parent_->GetDelegate())
-    parent_->GetDelegate()->BlockSiteData(false);
+  if (!signaled_)
+    parent_->BlockSiteData(false);
   parent_->CompleteDialog();
 }
 
@@ -113,17 +114,12 @@
 void CookiePromptView::ButtonPressed(views::Button* sender,
                                      const views::Event& event) {
   if (sender == allow_button_) {
-    if (parent_->GetDelegate()) {
-      parent_->GetDelegate()->AllowSiteData(remember_radio_->checked(),
-                                            session_expire_);
-      signaled_ = true;
-    }
+    parent_->AllowSiteData(remember_radio_->checked(), session_expire_);
+    signaled_ = true;
     GetWindow()->Close();
   } else if (sender == block_button_) {
-    if (parent_->GetDelegate()) {
-      parent_->GetDelegate()->BlockSiteData(remember_radio_->checked());
-      signaled_ = true;
-    }
+    parent_->BlockSiteData(remember_radio_->checked());
+    signaled_ = true;
     GetWindow()->Close();
   }
 }
@@ -244,6 +240,12 @@
                     parent_->local_storage_key(),
                     parent_->local_storage_value());
     info_view_ = view;
+  } else if (type == CookiePromptModalDialog::DIALOG_TYPE_DATABASE) {
+    DatabaseOpenInfoView* view = new DatabaseOpenInfoView();
+    layout->AddView(view, 1, 1, GridLayout::FILL, GridLayout::CENTER);
+    view->SetFields(parent_->origin().host(),
+                    parent_->database_name());
+    info_view_ = view;
   } else {
     NOTIMPLEMENTED();
   }
diff --git a/chrome/browser/views/database_open_info_view.cc b/chrome/browser/views/database_open_info_view.cc
new file mode 100755
index 0000000..20b315b4
--- /dev/null
+++ b/chrome/browser/views/database_open_info_view.cc
@@ -0,0 +1,107 @@
+// 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/views/database_open_info_view.h"
+
+#include <algorithm>
+
+#include "app/gfx/color_utils.h"
+#include "app/l10n_util.h"
+#include "base/i18n/time_formatting.h"
+#include "base/string_util.h"
+#include "grit/generated_resources.h"
+#include "views/grid_layout.h"
+#include "views/controls/label.h"
+#include "views/controls/textfield/textfield.h"
+#include "views/standard_layout.h"
+
+static const int kDatabaseOpenInfoViewBorderSize = 1;
+static const int kDatabaseOpenInfoViewInsetSize = 3;
+
+///////////////////////////////////////////////////////////////////////////////
+// DatabaseOpenInfoView, public:
+
+DatabaseOpenInfoView::DatabaseOpenInfoView()
+    : host_value_field_(NULL),
+      database_name_value_field_(NULL) {
+}
+
+DatabaseOpenInfoView::~DatabaseOpenInfoView() {
+}
+
+void DatabaseOpenInfoView::SetFields(const std::string& host,
+                                     const string16& database_name) {
+  host_value_field_->SetText(UTF8ToWide(host));
+  database_name_value_field_->SetText(database_name);
+  EnableDisplay(true);
+}
+
+void DatabaseOpenInfoView::EnableDisplay(bool enabled) {
+  host_value_field_->SetEnabled(enabled);
+  database_name_value_field_->SetEnabled(enabled);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// DatabaseOpenInfoView, views::View overrides:
+
+void DatabaseOpenInfoView::ViewHierarchyChanged(bool is_add,
+                                                views::View* parent,
+                                                views::View* child) {
+  if (is_add && child == this)
+    Init();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// DatabaseOpenInfoView, private:
+
+void DatabaseOpenInfoView::Init() {
+  SkColor border_color = color_utils::GetSysSkColor(COLOR_3DSHADOW);
+  views::Border* border = views::Border::CreateSolidBorder(
+      kDatabaseOpenInfoViewBorderSize, border_color);
+  set_border(border);
+
+  // TODO(jorlow): These strings are not quite right, but we're post-freeze.
+  views::Label* host_label = new views::Label(
+      l10n_util::GetString(IDS_COOKIES_COOKIE_DOMAIN_LABEL));
+  host_value_field_ = new views::Textfield;
+  views::Label* database_name_label = new views::Label(
+      l10n_util::GetString(IDS_COOKIES_COOKIE_NAME_LABEL));
+  database_name_value_field_ = new views::Textfield;
+
+  using views::GridLayout;
+
+  GridLayout* layout = new GridLayout(this);
+  layout->SetInsets(kDatabaseOpenInfoViewInsetSize,
+                    kDatabaseOpenInfoViewInsetSize,
+                    kDatabaseOpenInfoViewInsetSize,
+                    kDatabaseOpenInfoViewInsetSize);
+  SetLayoutManager(layout);
+
+  int three_column_layout_id = 0;
+  views::ColumnSet* column_set = layout->AddColumnSet(three_column_layout_id);
+  column_set->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
+                        GridLayout::USE_PREF, 0, 0);
+  column_set->AddPaddingColumn(0, kRelatedControlHorizontalSpacing);
+  column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
+                        GridLayout::USE_PREF, 0, 0);
+
+  layout->StartRow(0, three_column_layout_id);
+  layout->AddView(host_label);
+  layout->AddView(host_value_field_);
+  layout->AddPaddingRow(0, kRelatedControlSmallVerticalSpacing);
+  layout->StartRow(0, three_column_layout_id);
+  layout->AddView(database_name_label);
+  layout->AddView(database_name_value_field_);
+
+  // Color these borderless text areas the same as the containing dialog.
+  SkColor text_area_background = color_utils::GetSysSkColor(COLOR_3DFACE);
+  // Now that the Textfields are in the view hierarchy, we can initialize them.
+  host_value_field_->SetReadOnly(true);
+  host_value_field_->RemoveBorder();
+  host_value_field_->SetBackgroundColor(text_area_background);
+  database_name_value_field_->SetReadOnly(true);
+  database_name_value_field_->RemoveBorder();
+  database_name_value_field_->SetBackgroundColor(text_area_background);
+}
+
diff --git a/chrome/browser/views/database_open_info_view.h b/chrome/browser/views/database_open_info_view.h
new file mode 100755
index 0000000..84954f5
--- /dev/null
+++ b/chrome/browser/views/database_open_info_view.h
@@ -0,0 +1,54 @@
+// 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_VIEWS_DATABASE_OPEN_INFO_VIEW_H_
+#define CHROME_BROWSER_VIEWS_DATABASE_OPEN_INFO_VIEW_H_
+
+#include <string>
+#include <vector>
+
+#include "base/string16.h"
+#include "views/view.h"
+
+namespace views {
+class Label;
+class Textfield;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// DatabaseOpenInfoView
+//
+//  Responsible for displaying a tabular grid of Database information when
+//  prompting for permission to open a new database.
+class DatabaseOpenInfoView : public views::View {
+ public:
+  DatabaseOpenInfoView();
+  virtual ~DatabaseOpenInfoView();
+
+  // Update the display from the specified Database data.
+  void SetFields(const std::string& host,
+                 const string16& database_name);
+
+  // Enables or disables the local storate property text fields.
+  void EnableDisplay(bool enabled);
+
+ protected:
+  // views::View overrides:
+  virtual void ViewHierarchyChanged(
+      bool is_add, views::View* parent, views::View* child);
+
+ private:
+  // Set up the view layout
+  void Init();
+
+  // Individual property labels
+  views::Textfield* host_value_field_;
+  views::Textfield* database_name_value_field_;
+
+  DISALLOW_COPY_AND_ASSIGN(DatabaseOpenInfoView);
+};
+
+
+#endif  // CHROME_BROWSER_VIEWS_DATABASE_OPEN_INFO_VIEW_H_
+
diff --git a/chrome/browser/views/local_storage_set_item_info_view.cc b/chrome/browser/views/local_storage_set_item_info_view.cc
index b55934e..699c2f5 100755
--- a/chrome/browser/views/local_storage_set_item_info_view.cc
+++ b/chrome/browser/views/local_storage_set_item_info_view.cc
@@ -58,9 +58,8 @@
 ///////////////////////////////////////////////////////////////////////////////
 // LocalStorageSetItemInfoView, views::View overrides:
 
-void LocalStorageSetItemInfoView::ViewHierarchyChanged(bool is_add,
-                                                views::View* parent,
-                                                views::View* child) {
+void LocalStorageSetItemInfoView::ViewHierarchyChanged(
+    bool is_add, views::View* parent, views::View* child) {
   if (is_add && child == this)
     Init();
 }
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 8ae8229..15c0037 100755
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1979,6 +1979,8 @@
         'browser/views/jsmessage_box_dialog.h',
         'browser/views/keyword_editor_view.cc',
         'browser/views/keyword_editor_view.h',
+        'browser/views/database_open_info_view.cc',
+        'browser/views/database_open_info_view.h',
         'browser/views/local_storage_info_view.cc',
         'browser/views/local_storage_info_view.h',
         'browser/views/local_storage_set_item_info_view.cc',