Fixed a bug with the unit_tests, which caused it to leave hebrew enabled
vista without hebrew support
the bug reason is documented in the source for all to see and the bug=12093 (http://code.google.com/p/chromium/issues/detail?id=12093)

the code has been tested with and without a debugger but i have to admit, the unit_tests rarely pass on my machine (the ui ones never do)but this code i changed leaves the state EXACTLY like it was and solves this issue at least

BUG=12093
TEST=run unit_tests.exe on Hebrew Windows; run Chrome; open a page which contains a <textarea dir="ltr"></textarea> element; press control+right-shift key, and; verify its "dir" attribute becomes "rtl".
Review URL: http://codereview.chromium.org/115849

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@17156 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/renderer/mock_keyboard_driver_win.cc b/chrome/renderer/mock_keyboard_driver_win.cc
index 07792e9..151cb0b 100644
--- a/chrome/renderer/mock_keyboard_driver_win.cc
+++ b/chrome/renderer/mock_keyboard_driver_win.cc
@@ -15,28 +15,47 @@
   // should save the layout and status here to restore when this instance is
   // destroyed.
   original_keyboard_layout_ = GetKeyboardLayout(0);
+  active_keyboard_layout_ = original_keyboard_layout_;
   GetKeyboardState(&original_keyboard_states_[0]);
 
-  keyboard_handle_ = NULL;
+  const UINT num_keyboard_layouts = GetKeyboardLayoutList(0, NULL);
+  DCHECK(num_keyboard_layouts > 0);
+
+  orig_keyboard_layouts_list_.resize(num_keyboard_layouts);
+  GetKeyboardLayoutList(num_keyboard_layouts, &orig_keyboard_layouts_list_[0]);
+
   memset(&keyboard_states_[0], 0, sizeof(keyboard_states_));
 }
 
 MockKeyboardDriverWin::~MockKeyboardDriverWin() {
   // Unload the keyboard-layout driver, restore the keyboard state, and reset
   // the keyboard layout for succeeding tests.
-  if (keyboard_handle_)
-    UnloadKeyboardLayout(keyboard_handle_);
+  MaybeUnloadActiveLayout();
   SetKeyboardState(&original_keyboard_states_[0]);
   ActivateKeyboardLayout(original_keyboard_layout_, KLF_RESET);
 }
 
+void MockKeyboardDriverWin::MaybeUnloadActiveLayout() {
+  // Workaround for http://crbug.com/12093
+  // Only unload a keyboard layout if it was loaded by this mock driver.
+  // Contrary to the documentation on MSDN unloading a keyboard layout
+  // previously loaded by the system causes that layout to stop working.
+  // We have confirmation of this behavior on XP & Vista.
+  for (size_t i = 0; i < orig_keyboard_layouts_list_.size(); ++i) {
+    if (orig_keyboard_layouts_list_[i] == active_keyboard_layout_)
+      return;
+  }
+
+  // If we got here, this keyboard layout wasn't loaded by the system so it's
+  // safe to unload it ourselve's.
+  UnloadKeyboardLayout(active_keyboard_layout_);
+  active_keyboard_layout_ = original_keyboard_layout_;
+}
+
 bool MockKeyboardDriverWin::SetLayout(int layout) {
   // Unload the current keyboard-layout driver and load a new keyboard-layout
   // driver for mapping a virtual key-code to a Unicode character.
-  if (keyboard_handle_) {
-    UnloadKeyboardLayout(keyboard_handle_);
-    keyboard_handle_ = NULL;
-  }
+  MaybeUnloadActiveLayout();
 
   // Scan the mapping table and retrieve a Language ID for the input layout.
   // Load the keyboard-layout driver when we find a Language ID.
@@ -81,11 +100,16 @@
 
   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kLanguageIDs); ++i) {
     if (layout == kLanguageIDs[i].keyboard_layout) {
-      keyboard_handle_ = LoadKeyboardLayout(kLanguageIDs[i].language,
-                                            KLF_ACTIVATE);
-      if (!keyboard_handle_)
-        return false;
-      return true;
+      HKL new_keyboard_layout = LoadKeyboardLayout(kLanguageIDs[i].language,
+                                                   KLF_ACTIVATE);
+      // loaded_keyboard_layout_ must always have a valid keyboard handle
+      // so we only assign upon success.
+      if (new_keyboard_layout) {
+        active_keyboard_layout_ = new_keyboard_layout;
+        return true;
+      }
+
+      return false;
     }
   }
 
@@ -133,7 +157,7 @@
   int length = ToUnicodeEx(key_code, MapVirtualKey(key_code, 0),
                            &keyboard_states_[0], &code[0],
                            ARRAYSIZE_UNSAFE(code), 0,
-                           keyboard_handle_);
+                           active_keyboard_layout_);
   if (length > 0)
     output->assign(code);
   return length;