Do not give instant focus if a view's toplevelwidget is not active

If the top level widget isn't active during setting focus view, we store the focused view and then attempt to activate the widget. If activation succeeds view will be focused. If activation fails |view| will be focused the next time the widget is made active.

Based on this rule, a set of unittests related are modified.

This is a following up CL for 2113163002 as there are already too many patches there.

BUG=621791
BUG=650776
BUG=152938
TEST=add an interactive_ui_test, NativeWidgetAuraTest.NonActiveWindowRequestImeFocus

Review-Url: https://chromiumcodereview.appspot.com/2371113003
Cr-Commit-Position: refs/heads/master@{#426905}
diff --git a/ash/common/system/tray/tray_details_view_unittest.cc b/ash/common/system/tray/tray_details_view_unittest.cc
index c5ea6a6..86b6251 100644
--- a/ash/common/system/tray/tray_details_view_unittest.cc
+++ b/ash/common/system/tray/tray_details_view_unittest.cc
@@ -171,6 +171,7 @@
 
   // Transition back to default view, the default view of item 2 should have
   // focus.
+  tray->GetSystemBubble()->bubble_view()->set_can_activate(true);
   if (MaterialDesignController::IsSystemTrayMenuMaterial())
     FocusBackButton(test_item_2->detailed_view());
   else
diff --git a/chrome/browser/ui/ash/accessibility/ax_tree_source_aura_unittest.cc b/chrome/browser/ui/ash/accessibility/ax_tree_source_aura_unittest.cc
index 9ab38dd..f6befed 100644
--- a/chrome/browser/ui/ash/accessibility/ax_tree_source_aura_unittest.cc
+++ b/chrome/browser/ui/ash/accessibility/ax_tree_source_aura_unittest.cc
@@ -55,8 +55,8 @@
     AshTestBase::SetUp();
 
     widget_ = new Widget();
-    Widget::InitParams init_params(Widget::InitParams::TYPE_POPUP);
-    init_params.parent = CurrentContext();
+    Widget::InitParams init_params(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
+    init_params.context = CurrentContext();
     widget_->Init(init_params);
 
     content_ = new View();
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_ash_unittest.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_ash_unittest.cc
index abf2dbb1..c4a9715 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_ash_unittest.cc
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_ash_unittest.cc
@@ -45,6 +45,7 @@
         widget_->GetNativeWindow(), extension_environment_.profile(),
         extension_environment_.MakePackagedApp(kTestExtensionId, true).get());
     widget_->GetContentsView()->AddChildView(dialog_);
+    widget_->Show();
   }
 
   void TearDown() override {
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view_browsertest.cc b/chrome/browser/ui/views/toolbar/toolbar_view_browsertest.cc
deleted file mode 100644
index 7fc42ce..0000000
--- a/chrome/browser/ui/views/toolbar/toolbar_view_browsertest.cc
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright 2013 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/ui/views/toolbar/toolbar_view.h"
-
-#include <stddef.h>
-
-#include "base/macros.h"
-#include "base/strings/utf_string_conversions.h"
-#include "build/build_config.h"
-#include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/bookmarks/bookmark_model_factory.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_command_controller.h"
-#include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/view_ids.h"
-#include "chrome/browser/ui/views/frame/browser_view.h"
-#include "chrome/test/base/in_process_browser_test.h"
-#include "components/bookmarks/browser/bookmark_model.h"
-#include "components/bookmarks/browser/bookmark_utils.h"
-#include "ui/views/focus/focus_manager.h"
-#include "ui/views/view.h"
-#include "ui/views/widget/widget.h"
-
-using bookmarks::BookmarkModel;
-
-namespace {
-
-class ToolbarViewTest : public InProcessBrowserTest {
- public:
-  ToolbarViewTest() {}
-
-  void RunToolbarCycleFocusTest(Browser* browser);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ToolbarViewTest);
-};
-
-void ToolbarViewTest::RunToolbarCycleFocusTest(Browser* browser) {
-  gfx::NativeWindow window = browser->window()->GetNativeWindow();
-  views::Widget* widget = views::Widget::GetWidgetForNativeWindow(window);
-  views::FocusManager* focus_manager = widget->GetFocusManager();
-  CommandUpdater* updater = browser->command_controller()->command_updater();
-
-  // Send focus to the toolbar as if the user pressed Alt+Shift+T.
-  updater->ExecuteCommand(IDC_FOCUS_TOOLBAR);
-
-  views::View* first_view = focus_manager->GetFocusedView();
-  std::vector<int> ids;
-
-  // Press Tab to cycle through all of the controls in the toolbar until
-  // we end up back where we started.
-  bool found_reload = false;
-  bool found_location_bar = false;
-  bool found_app_menu = false;
-  const views::View* view = NULL;
-  while (view != first_view) {
-    focus_manager->AdvanceFocus(false);
-    view = focus_manager->GetFocusedView();
-    ids.push_back(view->id());
-    if (view->id() == VIEW_ID_RELOAD_BUTTON)
-      found_reload = true;
-    if (view->id() == VIEW_ID_APP_MENU)
-      found_app_menu = true;
-    if (view->id() == VIEW_ID_OMNIBOX)
-      found_location_bar = true;
-    if (ids.size() > 100)
-      GTEST_FAIL() << "Tabbed 100 times, still haven't cycled back!";
-  }
-
-  // Make sure we found a few key items.
-  ASSERT_TRUE(found_reload);
-  ASSERT_TRUE(found_app_menu);
-  ASSERT_TRUE(found_location_bar);
-
-  // Now press Shift-Tab to cycle backwards.
-  std::vector<int> reverse_ids;
-  view = NULL;
-  while (view != first_view) {
-    focus_manager->AdvanceFocus(true);
-    view = focus_manager->GetFocusedView();
-    reverse_ids.push_back(view->id());
-    if (reverse_ids.size() > 100)
-      GTEST_FAIL() << "Tabbed 100 times, still haven't cycled back!";
-  }
-
-  // Assert that the views were focused in exactly the reverse order.
-  // The sequences should be the same length, and the last element will
-  // be the same, and the others are reverse.
-  ASSERT_EQ(ids.size(), reverse_ids.size());
-  size_t count = ids.size();
-  for (size_t i = 0; i < count - 1; i++)
-    EXPECT_EQ(ids[i], reverse_ids[count - 2 - i]);
-}
-
-// The test is flaky on Win (http://crbug.com/152938) and crashes on CrOS under
-// AddressSanitizer (http://crbug.com/154657).
-IN_PROC_BROWSER_TEST_F(ToolbarViewTest, DISABLED_ToolbarCycleFocus) {
-  RunToolbarCycleFocusTest(browser());
-}
-
-#if defined(OS_WIN)
-// http://crbug.com/152938 Flaky on win.
-#define MAYBE_ToolbarCycleFocusWithBookmarkBar \
-    DISABLED_ToolbarCycleFocusWithBookmarkBar
-#else
-#define MAYBE_ToolbarCycleFocusWithBookmarkBar ToolbarCycleFocusWithBookmarkBar
-#endif
-IN_PROC_BROWSER_TEST_F(ToolbarViewTest,
-                       MAYBE_ToolbarCycleFocusWithBookmarkBar) {
-  CommandUpdater* updater = browser()->command_controller()->command_updater();
-  updater->ExecuteCommand(IDC_SHOW_BOOKMARK_BAR);
-
-  BookmarkModel* model =
-      BookmarkModelFactory::GetForBrowserContext(browser()->profile());
-  bookmarks::AddIfNotBookmarked(
-      model, GURL("http://foo.com"), base::ASCIIToUTF16("Foo"));
-
-  // We want to specifically test the case where the bookmark bar is
-  // already showing when a window opens, so create a second browser
-  // window with the same profile.
-  Browser* second_browser = CreateBrowser(browser()->profile());
-  RunToolbarCycleFocusTest(second_browser);
-}
-
-}  // namespace
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view_interactive_uitest.cc b/chrome/browser/ui/views/toolbar/toolbar_view_interactive_uitest.cc
index aabacfb..126b2a2 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_view_interactive_uitest.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_view_interactive_uitest.cc
@@ -2,20 +2,38 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
+
+#include <stddef.h>
+
 #include "base/location.h"
+#include "base/macros.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
+#include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_command_controller.h"
+#include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/toolbar/toolbar_actions_bar.h"
+#include "chrome/browser/ui/view_ids.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/frame/test_with_browser_view.h"
 #include "chrome/browser/ui/views/toolbar/app_menu_button.h"
 #include "chrome/browser/ui/views/toolbar/browser_actions_container.h"
 #include "chrome/browser/ui/views/toolbar/extension_toolbar_menu_view.h"
-#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
+#include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/interactive_test_utils.h"
+#include "components/bookmarks/browser/bookmark_model.h"
+#include "components/bookmarks/browser/bookmark_utils.h"
 #include "extensions/common/feature_switch.h"
+#include "ui/views/focus/focus_manager.h"
+#include "ui/views/test/widget_test.h"
+#include "ui/views/view.h"
+#include "ui/views/widget/widget.h"
 
 // Borrowed from chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc,
 // since these are also disabled on Linux for drag and drop.
@@ -26,6 +44,8 @@
 #define MAYBE(x) x
 #endif
 
+using bookmarks::BookmarkModel;
+
 class ToolbarViewInteractiveUITest : public ExtensionBrowserTest {
  public:
   ToolbarViewInteractiveUITest();
@@ -170,3 +190,97 @@
   // which should open the app menu.
   DoDragAndDrop(browser_action_view_loc, app_button_loc);
 }
+
+class ToolbarViewTest : public InProcessBrowserTest {
+ public:
+  ToolbarViewTest() {}
+
+  void RunToolbarCycleFocusTest(Browser* browser);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ToolbarViewTest);
+};
+
+void ToolbarViewTest::RunToolbarCycleFocusTest(Browser* browser) {
+  gfx::NativeWindow window = browser->window()->GetNativeWindow();
+  views::Widget* widget = views::Widget::GetWidgetForNativeWindow(window);
+  views::FocusManager* focus_manager = widget->GetFocusManager();
+  CommandUpdater* updater = browser->command_controller()->command_updater();
+
+  // Send focus to the toolbar as if the user pressed Alt+Shift+T.
+  updater->ExecuteCommand(IDC_FOCUS_TOOLBAR);
+
+  // Test relies on browser window activation, while platform such as Linux's
+  // window activation is asynchronous.
+  views::test::WidgetActivationWaiter waiter(widget, true);
+  waiter.Wait();
+
+  views::View* first_view = focus_manager->GetFocusedView();
+  std::vector<int> ids;
+
+  // Press Tab to cycle through all of the controls in the toolbar until
+  // we end up back where we started.
+  bool found_reload = false;
+  bool found_location_bar = false;
+  bool found_app_menu = false;
+  const views::View* view = NULL;
+  while (view != first_view) {
+    focus_manager->AdvanceFocus(false);
+    view = focus_manager->GetFocusedView();
+    ids.push_back(view->id());
+    if (view->id() == VIEW_ID_RELOAD_BUTTON)
+      found_reload = true;
+    if (view->id() == VIEW_ID_APP_MENU)
+      found_app_menu = true;
+    if (view->id() == VIEW_ID_OMNIBOX)
+      found_location_bar = true;
+    if (ids.size() > 100)
+      GTEST_FAIL() << "Tabbed 100 times, still haven't cycled back!";
+  }
+
+  // Make sure we found a few key items.
+  ASSERT_TRUE(found_reload);
+  ASSERT_TRUE(found_app_menu);
+  ASSERT_TRUE(found_location_bar);
+
+  // Now press Shift-Tab to cycle backwards.
+  std::vector<int> reverse_ids;
+  view = NULL;
+  while (view != first_view) {
+    focus_manager->AdvanceFocus(true);
+    view = focus_manager->GetFocusedView();
+    reverse_ids.push_back(view->id());
+    if (reverse_ids.size() > 100)
+      GTEST_FAIL() << "Tabbed 100 times, still haven't cycled back!";
+  }
+
+  // Assert that the views were focused in exactly the reverse order.
+  // The sequences should be the same length, and the last element will
+  // be the same, and the others are reverse.
+  ASSERT_EQ(ids.size(), reverse_ids.size());
+  size_t count = ids.size();
+  for (size_t i = 0; i < count - 1; i++)
+    EXPECT_EQ(ids[i], reverse_ids[count - 2 - i]);
+}
+
+// The test is flaky on Win (http://crbug.com/152938) and crashes on CrOS under
+// AddressSanitizer (http://crbug.com/154657).
+IN_PROC_BROWSER_TEST_F(ToolbarViewTest, DISABLED_ToolbarCycleFocus) {
+  RunToolbarCycleFocusTest(browser());
+}
+
+IN_PROC_BROWSER_TEST_F(ToolbarViewTest, ToolbarCycleFocusWithBookmarkBar) {
+  CommandUpdater* updater = browser()->command_controller()->command_updater();
+  updater->ExecuteCommand(IDC_SHOW_BOOKMARK_BAR);
+
+  BookmarkModel* model =
+      BookmarkModelFactory::GetForBrowserContext(browser()->profile());
+  bookmarks::AddIfNotBookmarked(model, GURL("http://foo.com"),
+                                base::ASCIIToUTF16("Foo"));
+
+  // We want to specifically test the case where the bookmark bar is
+  // already showing when a window opens, so create a second browser
+  // window with the same profile.
+  Browser* second_browser = CreateBrowser(browser()->profile());
+  RunToolbarCycleFocusTest(second_browser);
+}
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 469bb7f..fd0c8ce 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -589,6 +589,10 @@
           "//ui/views/widget/desktop_aura/x11_topmost_window_finder_interactive_uitest.cc",
         ]
       }
+      if (use_aura) {
+        sources +=
+            [ "//ui/views/widget/native_widget_aura_interactive_uitest.cc" ]
+      }
       if (use_aura || is_mac) {
         # TODO(ekaramad): These tests are activated for aura and mac only. They
         # should be moved to 'interactive_ui_tests' sources for all platforms
@@ -2122,7 +2126,6 @@
           "../browser/ui/views/passwords/password_dialog_view_browsertest.cc",
           "../browser/ui/views/task_manager_view_browsertest.cc",
           "../browser/ui/views/toolbar/browser_actions_container_browsertest.cc",
-          "../browser/ui/views/toolbar/toolbar_view_browsertest.cc",
           "../browser/ui/views/translate/translate_bubble_view_browsertest.cc",
           "../browser/ui/views/web_dialog_view_browsertest.cc",
         ]
diff --git a/ui/views/controls/combobox/combobox_unittest.cc b/ui/views/controls/combobox/combobox_unittest.cc
index ec9ade9..165165b 100644
--- a/ui/views/controls/combobox/combobox_unittest.cc
+++ b/ui/views/controls/combobox/combobox_unittest.cc
@@ -211,6 +211,7 @@
     View* container = new View();
     widget_->SetContentsView(container);
     container->AddChildView(combobox_);
+    widget_->Show();
 
     combobox_->RequestFocus();
     combobox_->SizeToPreferredSize();
diff --git a/ui/views/focus/focus_manager.cc b/ui/views/focus/focus_manager.cc
index d5858e28..7195108 100644
--- a/ui/views/focus/focus_manager.cc
+++ b/ui/views/focus/focus_manager.cc
@@ -313,6 +313,21 @@
   if (focused_view_ == view)
     return;
 
+#if !defined(OS_MACOSX)
+  // TODO(warx): There are some AccessiblePaneViewTest failed on macosx.
+  // crbug.com/650859. Remove !defined(OS_MACOSX) once that is fixed.
+  //
+  // If the widget isn't active store the focused view and then attempt to
+  // activate the widget. If activation succeeds |view| will be focused.
+  // If activation fails |view| will be focused the next time the widget is
+  // made active.
+  if (view && !widget_->IsActive()) {
+    SetStoredFocusView(view);
+    widget_->Activate();
+    return;
+  }
+#endif
+
   base::AutoReset<bool> auto_changing_focus(&is_changing_focus_, true);
   // Update the reason for the focus change (since this is checked by
   // some listeners), then notify all listeners.
diff --git a/ui/views/mus/native_widget_mus.cc b/ui/views/mus/native_widget_mus.cc
index ea6c6eb..a957db86 100644
--- a/ui/views/mus/native_widget_mus.cc
+++ b/ui/views/mus/native_widget_mus.cc
@@ -1116,11 +1116,11 @@
 }
 
 void NativeWidgetMus::Activate() {
+  if (!window_)
+    return;
+
   static_cast<aura::client::ActivationClient*>(focus_client_.get())
       ->ActivateWindow(content_);
-  // FocusControllerMus should have focused |window_| when |content_| is
-  // activated.
-  DCHECK(!window_ || window_->HasFocus());
 }
 
 void NativeWidgetMus::Deactivate() {
diff --git a/ui/views/view_targeter_unittest.cc b/ui/views/view_targeter_unittest.cc
index 620cfea..d72a26a 100644
--- a/ui/views/view_targeter_unittest.cc
+++ b/ui/views/view_targeter_unittest.cc
@@ -125,6 +125,7 @@
       CreateParams(Widget::InitParams::TYPE_POPUP);
   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   widget.Init(init_params);
+  widget.Show();
 
   View* content = new View;
   View* child = new View;
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
index 9088c5a..f6d0a352 100644
--- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
+++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
@@ -350,12 +350,14 @@
       // This function can be called before the focus manager has had a
       // chance to set the focused view. In which case we should get the
       // last focused view.
-      View* view_for_activation =
-          GetWidget()->GetFocusManager()->GetFocusedView() ?
-              GetWidget()->GetFocusManager()->GetFocusedView() :
-                  GetWidget()->GetFocusManager()->GetStoredFocusView();
+      views::FocusManager* focus_manager = GetWidget()->GetFocusManager();
+      View* view_for_activation = focus_manager->GetFocusedView()
+                                      ? focus_manager->GetFocusedView()
+                                      : focus_manager->GetStoredFocusView();
       if (!view_for_activation)
         view_for_activation = GetWidget()->GetRootView();
+      else if (view_for_activation == focus_manager->GetStoredFocusView())
+        focus_manager->RestoreFocusedView();
       activation_client->ActivateWindow(
           view_for_activation->GetWidget()->GetNativeView());
       // Refreshes the focus info to IMF in case that IMF cached the old info
diff --git a/ui/views/widget/native_widget_aura_interactive_uitest.cc b/ui/views/widget/native_widget_aura_interactive_uitest.cc
new file mode 100644
index 0000000..299bc50b
--- /dev/null
+++ b/ui/views/widget/native_widget_aura_interactive_uitest.cc
@@ -0,0 +1,130 @@
+// Copyright 2016 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 "ui/views/widget/native_widget_aura.h"
+
+#include "base/path_service.h"
+#include "ui/aura/window.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/ui_base_paths.h"
+#include "ui/gl/test/gl_surface_test_support.h"
+#include "ui/views/controls/textfield/textfield.h"
+#include "ui/views/test/native_widget_factory.h"
+#include "ui/views/test/views_test_base.h"
+#include "ui/views/test/widget_test.h"
+#include "ui/views/widget/widget_delegate.h"
+#include "ui/wm/core/base_focus_rules.h"
+#include "ui/wm/core/focus_controller.h"
+
+namespace views {
+namespace test {
+
+class TestFocusRules : public wm::BaseFocusRules {
+ public:
+  TestFocusRules() {}
+  ~TestFocusRules() override {}
+
+  void set_can_activate(bool can_activate) { can_activate_ = can_activate; }
+
+  // wm::BaseFocusRules overrides:
+  bool SupportsChildActivation(aura::Window* window) const override {
+    return true;
+  }
+
+  bool CanActivateWindow(aura::Window* window) const override {
+    return can_activate_;
+  }
+
+ private:
+  bool can_activate_ = true;
+
+  DISALLOW_COPY_AND_ASSIGN(TestFocusRules);
+};
+
+class NativeWidgetAuraTest : public ViewsTestBase {
+ public:
+  NativeWidgetAuraTest() {}
+  ~NativeWidgetAuraTest() override {}
+
+  void SetUp() override {
+    gl::GLSurfaceTestSupport::InitializeOneOff();
+    ui::RegisterPathProvider();
+    base::FilePath ui_test_pak_path;
+    ASSERT_TRUE(PathService::Get(ui::UI_TEST_PAK, &ui_test_pak_path));
+    ui::ResourceBundle::InitSharedInstanceWithPakPath(ui_test_pak_path);
+
+    ViewsTestBase::SetUp();
+  }
+
+  NativeWidget* CreateNativeWidget(const Widget::InitParams& params,
+                                   Widget* widget) {
+    return CreatePlatformNativeWidgetImpl(params, widget, kDefault, nullptr);
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(NativeWidgetAuraTest);
+};
+
+// When requesting view focus from a non-active top level widget, focus is not
+// instantly given. Instead, the view is firstly stored and then it is attempted
+// to activate the widget. If widget is currently not activatable, focus should
+// not be grabbed. And focus will be given/restored the next time the widget is
+// made active. (crbug.com/621791)
+TEST_F(NativeWidgetAuraTest, NonActiveWindowRequestImeFocus) {
+  TestFocusRules* test_focus_rules = new TestFocusRules;
+  std::unique_ptr<wm::FocusController> focus_controller =
+      base::MakeUnique<wm::FocusController>(test_focus_rules);
+  aura::client::SetActivationClient(GetContext(), focus_controller.get());
+
+  Widget* widget1 = new Widget;
+  Widget::InitParams params1(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
+  params1.context = GetContext();
+  params1.native_widget = CreateNativeWidget(params1, widget1);
+  params1.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+  widget1->Init(params1);
+  Textfield* textfield1 = new Textfield;
+  widget1->GetRootView()->AddChildView(textfield1);
+
+  Widget* widget2 = new Widget;
+  Widget::InitParams params2(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
+  params2.context = GetContext();
+  params2.native_widget = CreateNativeWidget(params2, widget2);
+  params2.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+  widget2->Init(params2);
+  Textfield* textfield2a = new Textfield;
+  widget2->GetRootView()->AddChildView(textfield2a);
+  Textfield* textfield2b = new Textfield;
+  widget2->GetRootView()->AddChildView(textfield2b);
+
+  views::test::WidgetActivationWaiter waiter1(widget1, true);
+  widget1->Show();
+  waiter1.Wait();
+  textfield1->RequestFocus();
+  EXPECT_TRUE(textfield1->HasFocus());
+  EXPECT_FALSE(textfield2a->HasFocus());
+  EXPECT_FALSE(textfield2b->HasFocus());
+
+  // Don't allow window activation at this step.
+  test_focus_rules->set_can_activate(false);
+  textfield2a->RequestFocus();
+  EXPECT_TRUE(textfield1->HasFocus());
+  EXPECT_FALSE(textfield2a->HasFocus());
+  EXPECT_FALSE(textfield2b->HasFocus());
+
+  // Allow window activation and |widget2| gets activated at this step, focus
+  // should be properly restored.
+  test_focus_rules->set_can_activate(true);
+  views::test::WidgetActivationWaiter waiter2(widget2, true);
+  widget2->Activate();
+  waiter2.Wait();
+  EXPECT_TRUE(textfield2a->HasFocus());
+  EXPECT_FALSE(textfield2b->HasFocus());
+  EXPECT_FALSE(textfield1->HasFocus());
+
+  widget1->CloseNow();
+  widget2->CloseNow();
+}
+
+}  // namespace test
+}  // namespace views
diff --git a/ui/views/widget/root_view_unittest.cc b/ui/views/widget/root_view_unittest.cc
index 7c414a2..b4d712e8 100644
--- a/ui/views/widget/root_view_unittest.cc
+++ b/ui/views/widget/root_view_unittest.cc
@@ -44,6 +44,7 @@
       CreateParams(Widget::InitParams::TYPE_POPUP);
   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   widget.Init(init_params);
+  widget.Show();
 
   bool got_key_event = false;
 
@@ -114,6 +115,7 @@
       CreateParams(Widget::InitParams::TYPE_POPUP);
   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   widget.Init(init_params);
+  widget.Show();
   internal::RootView* root_view =
       static_cast<internal::RootView*>(widget.GetRootView());