예제 #1
0
int BrowserFactory::GetZoneProtectedModeSetting(const HKEY key_handle,
                                                const std::wstring& zone_subkey_name) {
  LOG(TRACE) << "Entering BrowserFactory::GetZoneProtectedModeSetting";

  int protected_mode_value = 3;
  HKEY subkey_handle;
  if (ERROR_SUCCESS == ::RegOpenKeyEx(key_handle,
                                      zone_subkey_name.c_str(),
                                      0,
                                      KEY_QUERY_VALUE,
                                      &subkey_handle)) {
    DWORD value = 0;
    DWORD value_length = sizeof(DWORD);
    if (ERROR_SUCCESS == ::RegQueryValueEx(subkey_handle,
                                           IE_PROTECTED_MODE_SETTING_VALUE_NAME,
                                           NULL,
                                           NULL,
                                           reinterpret_cast<LPBYTE>(&value),
                                           &value_length)) {
      LOG(DEBUG) << "Found Protected Mode setting value of "
                 << value << " for zone " << LOGWSTRING(zone_subkey_name.c_str());
      protected_mode_value = value;
    } else {
      LOG(DEBUG) << "RegQueryValueEx failed for getting Protected Mode setting for a zone: "
                 << LOGWSTRING(zone_subkey_name.c_str());
    }
    ::RegCloseKey(subkey_handle);
  } else {
    // The REG_DWORD value doesn't exist, so we have to return the default
    // value, which is "on" for the Internet and Restricted Sites zones and
    // is "on" for the Local Intranet zone in IE7 only (the default was
    // changed to "off" for Local Intranet in IE8), and "off" everywhere
    // else.
    // Note that a value of 0 in the registry value indicates that Protected
    // Mode is "on" for that zone; a value of 3 indicates that Protected Mode
    // is "off" for that zone.
    if (zone_subkey_name == ZONE_INTERNET ||
        zone_subkey_name == ZONE_RESTRICTED_SITES ||
        (zone_subkey_name == ZONE_LOCAL_INTRANET && this->ie_major_version_ == 7)) {
      protected_mode_value = 0;
    }
    LOG(DEBUG) << "Protected Mode zone setting value does not exist for zone "
               << LOGWSTRING(zone_subkey_name.c_str()) << ". Using default value of "
               << protected_mode_value;
  }
  return protected_mode_value;
}
예제 #2
0
void BrowserFactory::LaunchBrowserUsingCreateProcess(const std::string& initial_url,
                                                     const std::string& command_line_switches,
                                                     PROCESS_INFORMATION* proc_info,
                                                     std::string* error_message) {
  LOG(TRACE) << "Entering BrowserFactory::LaunchBrowserUsingCreateProcess";
  LOG(DEBUG) << "Starting IE using the CreateProcess API";

  STARTUPINFO start_info;
  ::ZeroMemory(&start_info, sizeof(start_info));
  start_info.cb = sizeof(start_info);

  std::wstring wide_initial_url = StringUtilities::ToWString(initial_url);
  std::wstring wide_ie_switches = StringUtilities::ToWString(command_line_switches);

  std::wstring executable_and_url = this->ie_executable_location_;
  if (wide_ie_switches.size() != 0) {
    executable_and_url.append(L" ");
    executable_and_url.append(wide_ie_switches);
  }
  executable_and_url.append(L" ");
  executable_and_url.append(wide_initial_url);

  LOG(TRACE) << "IE starting command line is: '" << LOGWSTRING(executable_and_url) << "'.";

  LPWSTR command_line = new WCHAR[executable_and_url.size() + 1];
  wcscpy_s(command_line,
           executable_and_url.size() + 1,
           executable_and_url.c_str());
  command_line[executable_and_url.size()] = L'\0';
  BOOL create_process_result = ::CreateProcess(NULL,
                                               command_line,
                                               NULL,
                                               NULL,
                                               FALSE,
                                               0,
                                               NULL,
                                               NULL,
                                               &start_info,
                                               proc_info);
  if (!create_process_result) {
    int create_proc_msg_count = _scwprintf(CREATEPROCESS_ERROR_MESSAGE,
                                           command_line);
    vector<wchar_t> create_proc_result_msg(create_proc_msg_count + 1);
    _snwprintf_s(&create_proc_result_msg[0],
                  create_proc_result_msg.size(),
                  create_proc_msg_count,
                  CREATEPROCESS_ERROR_MESSAGE,
                  command_line);
    std::string launch_error = StringUtilities::ToString(&create_proc_result_msg[0]);
    *error_message = launch_error;
  }
  delete[] command_line;
}
예제 #3
0
void BrowserFactory::GetIEVersion() {
  LOG(TRACE) << "Entering BrowserFactory::GetIEVersion";

  struct LANGANDCODEPAGE {
    WORD language;
    WORD code_page;
    } *lpTranslate;

  DWORD dummy;
  DWORD length = ::GetFileVersionInfoSize(this->ie_executable_location_.c_str(),
                                          &dummy);
  if (length == 0) {
    // 64-bit Windows 8 has a bug where it does not return the executable location properly
    this->ie_major_version_ = -1;
    LOG(WARN) << "Couldn't find IE version for executable "
               << LOGWSTRING(this->ie_executable_location_.c_str())
               << ", falling back to "
               << this->ie_major_version_;
    return;
  }
  std::vector<BYTE> version_buffer(length);
  ::GetFileVersionInfo(this->ie_executable_location_.c_str(),
                       dummy,
                       length,
                       &version_buffer[0]);

  UINT page_count;
  BOOL query_result = ::VerQueryValue(&version_buffer[0],
                                      FILE_LANGUAGE_INFO,
                                      reinterpret_cast<void**>(&lpTranslate),
                                      &page_count);
    
  wchar_t sub_block[MAX_PATH];
  _snwprintf_s(sub_block,
               MAX_PATH,
               MAX_PATH,
               FILE_VERSION_INFO,
               lpTranslate->language,
               lpTranslate->code_page);
  LPVOID value = NULL;
  UINT size;
  query_result = ::VerQueryValue(&version_buffer[0],
                                 sub_block,
                                 &value,
                                 &size);
  std::wstring ie_version;
  ie_version.assign(static_cast<wchar_t*>(value));
  std::wstringstream version_stream(ie_version);
  version_stream >> this->ie_major_version_;
}
예제 #4
0
void BrowserFactory::GetIEVersion() {
  LOG(TRACE) << "Entering BrowserFactory::GetIEVersion";

  std::string ie_version = FileUtilities::GetFileVersion(this->ie_executable_location_);
  
  if (ie_version.size() == 0) {
    // 64-bit Windows 8 has a bug where it does not return the executable location properly
    this->ie_major_version_ = -1;
    LOG(WARN) << "Couldn't find IE version for executable "
               << LOGWSTRING(this->ie_executable_location_)
               << ", falling back to "
               << this->ie_major_version_;
    return;
  }

  std::stringstream version_stream(ie_version);
  version_stream >> this->ie_major_version_;
}
예제 #5
0
void BrowserFactory::LaunchBrowserUsingCreateProcess(PROCESS_INFORMATION* proc_info,
                                                     std::string* error_message) {
  LOG(TRACE) << "Entering BrowserFactory::LaunchBrowserUsingCreateProcess";
  LOG(DEBUG) << "Starting IE using the CreateProcess API";

  STARTUPINFO start_info;
  ::ZeroMemory(&start_info, sizeof(start_info));
  start_info.cb = sizeof(start_info);

  std::wstring executable_and_url = this->ie_executable_location_;
  if (this->browser_command_line_switches_.size() != 0) {
    executable_and_url.append(L" ");
    executable_and_url.append(this->browser_command_line_switches_);
  }
  executable_and_url.append(L" ");
  executable_and_url.append(this->initial_browser_url_);

  LOG(TRACE) << "IE starting command line is: '"
             << LOGWSTRING(executable_and_url) << "'.";

  LPWSTR command_line = new WCHAR[executable_and_url.size() + 1];
  wcscpy_s(command_line,
           executable_and_url.size() + 1,
           executable_and_url.c_str());
  command_line[executable_and_url.size()] = L'\0';
  BOOL create_process_result = ::CreateProcess(NULL,
                                               command_line,
                                               NULL,
                                               NULL,
                                               FALSE,
                                               0,
                                               NULL,
                                               NULL,
                                               &start_info,
                                               proc_info);
  if (!create_process_result) {
    *error_message = StringUtilities::Format(CREATEPROCESS_ERROR_MESSAGE,
                                             StringUtilities::ToString(command_line));
  }
  delete[] command_line;
}
bool DocumentHost::IsHtmlPage(IHTMLDocument2* doc) {
  LOG(TRACE) << "Entering DocumentHost::IsHtmlPage";

  CComBSTR type;
  if (!SUCCEEDED(doc->get_mimeType(&type))) {
    LOG(WARN) << "Unable to get mime type for document, call to IHTMLDocument2::get_mimeType failed";
    return false;
  }

  std::wstring document_type_key_name= L"";
  if (this->factory_.GetRegistryValue(HKEY_CURRENT_USER,
                                      L"Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\http\\UserChoice",
                                      L"Progid",
                                      &document_type_key_name)) {
    // Look for the user-customization under Vista/Windows 7 first. If it's
    // IE, set the document friendly name lookup key to 'htmlfile'. If not,
    // set it to blank so that we can look up the proper HTML type.
    if (document_type_key_name == L"IE.HTTP") {
      document_type_key_name = L"htmlfile";
    } else {
      LOG(DEBUG) << "Unable to support custom document type: " << LOGWSTRING(document_type_key_name.c_str());
      document_type_key_name = L"";
    }
  } else {
    LOG(DEBUG) << "Unable to read document type from registry";
  }

  if (document_type_key_name == L"") {
    // To be technically correct, we should look up the extension specified
    // for the text/html MIME type first (located in the "Extension" value
    // of HKEY_CLASSES_ROOT\MIME\Database\Content Type\text/html), but that
    // should always resolve to ".htm" anyway. From the extension, we can 
    // find the browser-specific subkey of HKEY_CLASSES_ROOT, the default 
    // value of which should contain the browser-specific friendly name of
    // the MIME type for HTML documents, which is what 
    // IHTMLDocument2::get_mimeType() returns.
    if (!this->factory_.GetRegistryValue(HKEY_CLASSES_ROOT,
                                         L".htm",
                                         L"",
                                         &document_type_key_name)) {
      LOG(WARN) << "Unable to read document type from registry for '.htm'";
      return false;
    }
  }

  // First try the (default) value for the subkey. Some browsers (Opera)
  // do not write this information in the (default) value, so if that fails,
  // try the FriendlyTypeName value.
  std::wstring mime_type_name;
  if (!this->factory_.GetRegistryValue(HKEY_CLASSES_ROOT,
                                       document_type_key_name,
                                       L"",
                                       &mime_type_name)) {
    if (!this->factory_.GetRegistryValue(HKEY_CLASSES_ROOT,
                                         document_type_key_name,
                                         L"FriendlyTypeName",
                                         &mime_type_name)) {
      LOG(WARN) << "Unable to read mime type from registry for document type";
      return false;
    }
  }

  std::wstring type_string = type;

  if (type_string == mime_type_name) {
	  return true;
  }

  // If the user set Firefox as a default browser at any point, the MIME type
  // appears to be "sticky". This isn't elegant, but it appears to alleviate
  // the worst symptoms. Tested by using both Safari and Opera as the default
  // browser, even after setting IE as the default after Firefox (so the chain
  // of defaults looks like (IE -> Firefox -> IE -> Opera)

  if (L"Firefox HTML Document" == mime_type_name) {
    LOG(INFO) << "It looks like Firefox was once the default browser. " 
        << "Guessing the page type from mime type alone";
    return true;
  }

  return false;
}
예제 #7
0
bool BrowserFactory::ProtectedModeSettingsAreValid() {
  LOG(TRACE) << "Entering BrowserFactory::ProtectedModeSettingsAreValid";

  bool settings_are_valid = true;
  LOG(DEBUG) << "Detected IE version: " << this->ie_major_version_
             << ", detected Windows version: " << this->windows_major_version_;
  // Only need to check Protected Mode settings on IE 7 or higher
  // and on Windows Vista or higher. Otherwise, Protected Mode
  // doesn't come into play, and are valid.
  // Documentation of registry settings can be found at the following
  // Microsoft KnowledgeBase article:
  // http://support.microsoft.com/kb/182569
  if (this->ie_major_version_ >= 7 && this->windows_major_version_ >= 6) {
    HKEY key_handle;
    if (ERROR_SUCCESS == ::RegOpenKeyEx(HKEY_CURRENT_USER,
                                        IE_SECURITY_ZONES_REGISTRY_KEY,
                                        0,
                                        KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
                                        &key_handle)) {
      DWORD subkey_count = 0;
      DWORD max_subkey_name_length = 0;
      if (ERROR_SUCCESS == ::RegQueryInfoKey(key_handle,
                                             NULL,
                                             NULL,
                                             NULL,
                                             &subkey_count,
                                             &max_subkey_name_length,
                                             NULL,
                                             NULL,
                                             NULL,
                                             NULL,
                                             NULL,
                                             NULL)) {
        int protected_mode_value = -1;
        std::vector<TCHAR> subkey_name_buffer(max_subkey_name_length + 1);
        for (size_t index = 0; index < subkey_count; ++index) {
          DWORD number_of_characters_copied = max_subkey_name_length + 1;
          ::RegEnumKeyEx(key_handle,
                         static_cast<DWORD>(index),
                         &subkey_name_buffer[0],
                         &number_of_characters_copied,
                         NULL,
                         NULL,
                         NULL,
                         NULL);
          std::wstring subkey_name = &subkey_name_buffer[0];
          // Ignore the "My Computer" zone, since it's not displayed
          // in the UI.
          if (subkey_name != ZONE_MY_COMPUTER) {
            int value = this->GetZoneProtectedModeSetting(key_handle,
                                                          subkey_name);
            if (protected_mode_value == -1) {
              protected_mode_value = value;
            } else {
              if (value != protected_mode_value) {
                settings_are_valid = false;
                break;
              }
            }
          }
        }
      } else {
        LOG(WARN) << "RegQueryInfoKey to get count of zone setting subkeys failed";
      }
      ::RegCloseKey(key_handle);
    } else {
      LOG(WARN) << "RegOpenKeyEx for zone settings registry key "
                << LOGWSTRING(IE_SECURITY_ZONES_REGISTRY_KEY)
                << " in HKEY_CURRENT_USER failed";
    }
  }
  return settings_are_valid;
}
예제 #8
0
bool BrowserFactory::GetRegistryValue(const HKEY root_key,
                                      const std::wstring& subkey,
                                      const std::wstring& value_name,
                                      std::wstring *value) {
  LOG(TRACE) << "Entering BrowserFactory::GetRegistryValue";

  std::string root_key_description = "HKEY_CURRENT_USER";
  if (root_key == HKEY_CLASSES_ROOT) {
    root_key_description = "HKEY_CLASSES_ROOT";
  } else if (root_key == HKEY_LOCAL_MACHINE) {
    root_key_description = "HKEY_LOCAL_MACHINE";
  }

  bool value_retrieved = false;
  DWORD required_buffer_size;
  HKEY key_handle;
  long registry_call_result = ::RegOpenKeyEx(root_key,
                                      subkey.c_str(),
                                      0,
                                      KEY_QUERY_VALUE,
                                      &key_handle);
  if (ERROR_SUCCESS == registry_call_result) {
    registry_call_result = ::RegQueryValueEx(key_handle,
                                           value_name.c_str(),
                                           NULL,
                                           NULL,
                                           NULL,
                                           &required_buffer_size);
    if (ERROR_SUCCESS == registry_call_result) {
      std::vector<TCHAR> value_buffer(required_buffer_size);
      DWORD value_type(0);
      registry_call_result = ::RegQueryValueEx(key_handle,
                                             value_name.c_str(),
                                             NULL,
                                             &value_type,
                                             reinterpret_cast<LPBYTE>(&value_buffer[0]),
                                             &required_buffer_size);
      if (ERROR_SUCCESS == registry_call_result) {
        *value = &value_buffer[0];
        value_retrieved = true;
      } else {
        LOG(WARN) << "RegQueryValueEx failed with error code "
                  << registry_call_result << " retrieving value with name "
                  << LOGWSTRING(value_name.c_str()) << " in subkey "
                  << LOGWSTRING(subkey.c_str()) << "in hive "
                  << root_key_description;
      }
    } else {
      LOG(WARN) << "RegQueryValueEx failed with error code "
                << registry_call_result
                << " retrieving required buffer size for value with name "
                << LOGWSTRING(value_name.c_str()) << " in subkey "
                << LOGWSTRING(subkey.c_str()) << "in hive "
                << root_key_description;
    }
    ::RegCloseKey(key_handle);
  } else {
    LOG(WARN) << "RegOpenKeyEx failed with error code "
              << registry_call_result <<  " attempting to open subkey "
              << LOGWSTRING(subkey.c_str()) << "in hive "
              << root_key_description;

  }
  return value_retrieved;
}
예제 #9
0
bool Browser::IsDocumentNavigating(IHTMLDocument2* doc) {
  LOG(TRACE) << "Entering Browser::IsDocumentNavigating";

  bool is_navigating = true;

  // Starting WaitForDocumentComplete()
  is_navigating = this->is_navigation_started_;
  CComBSTR ready_state;
  HRESULT hr = doc->get_readyState(&ready_state);
  if (FAILED(hr) || is_navigating || _wcsicmp(ready_state, L"complete") != 0) {
    if (FAILED(hr)) {
      LOGHR(DEBUG, hr) << "IHTMLDocument2::get_readyState failed.";
    } else if (is_navigating) {
      LOG(DEBUG) << "DocumentComplete event fired, indicating a new navigation.";
    } else {
      std::wstring state = ready_state;
      LOG(DEBUG) << "document.readyState is not 'complete'; it was " << LOGWSTRING(state);
    }
    return true;
  } else {
    is_navigating = false;
  }

  // document.readyState == complete
  is_navigating = this->is_navigation_started_;
  CComPtr<IHTMLFramesCollection2> frames;
  hr = doc->get_frames(&frames);
  if (is_navigating || FAILED(hr)) {
    LOG(DEBUG) << "Could not get frames, navigation has started or call to IHTMLDocument2::get_frames failed";
    return true;
  }

  if (frames != NULL) {
    long frame_count = 0;
    hr = frames->get_length(&frame_count);

    CComVariant index;
    index.vt = VT_I4;
    for (long i = 0; i < frame_count; ++i) {
      // Waiting on each frame
      index.lVal = i;
      CComVariant result;
      hr = frames->item(&index, &result);
      if (FAILED(hr)) {
        LOGHR(DEBUG, hr) << "Could not get frame item for index "
                         << i
                         << ", call to IHTMLFramesCollection2::item failed, frame/frameset is broken";
        continue;
      }

      CComPtr<IHTMLWindow2> window;
      result.pdispVal->QueryInterface<IHTMLWindow2>(&window);
      if (!window) {        
        LOG(DEBUG) << "Could not get window for frame item with index "
                   << i 
                   << ", cast to IHTMLWindow2 failed, frame is not an HTML frame";
        continue;
      }

      CComPtr<IHTMLDocument2> frame_document;
      bool is_valid_frame_document = this->GetDocumentFromWindow(window,
                                                                 &frame_document);

      is_navigating = this->is_navigation_started_;
      if (is_navigating) {
        break;
      }

      // Recursively call to wait for the frame document to complete
      if (is_valid_frame_document) {
        is_navigating = this->IsDocumentNavigating(frame_document);
        if (is_navigating) {
          break;
        }
      }
    }
  } else {
    LOG(DEBUG) << "IHTMLDocument2.get_frames() returned empty collection";
  }
  return is_navigating;
}
예제 #10
0
int ElementFinder::FindElements(const IECommandExecutor& executor,
                                const ElementHandle parent_wrapper,
                                const std::wstring& mechanism,
                                const std::wstring& criteria,
                                Json::Value* found_elements) {
  LOG(TRACE) << "Entering ElementFinder::FindElements";

  BrowserHandle browser;
  int status_code = executor.GetCurrentBrowser(&browser);
  if (status_code == WD_SUCCESS) {
    if (mechanism == L"css") {
      if (!this->HasNativeCssSelectorEngine(executor)) {
        LOG(DEBUG) << "Element location strategy is CSS selectors, but "
                   << "document does not support CSS selectors. Falling back "
                   << "to using the Sizzle JavaScript CSS selector engine.";
        return this->FindElementsUsingSizzle(executor,
                                             parent_wrapper,
                                             criteria,
                                             found_elements);
      }
    }

    LOG(DEBUG) << "Using FindElements atom to locate element having "
               << LOGWSTRING(mechanism) << " = "
               << LOGWSTRING(criteria);
    CComPtr<IHTMLDocument2> doc;
    browser->GetDocument(&doc);

    std::wstring script_source(L"(function() { return (");
    script_source += atoms::asString(atoms::FIND_ELEMENTS);
    script_source += L")})();";

    Script script_wrapper(doc, script_source, 3);
    script_wrapper.AddArgument(mechanism);
    script_wrapper.AddArgument(criteria);
    if (parent_wrapper) {
      script_wrapper.AddArgument(parent_wrapper->element());
    }

    status_code = script_wrapper.Execute();
    if (status_code == WD_SUCCESS) {
      Json::Value atom_result;
      script_wrapper.ConvertResultToJsonValue(executor, &atom_result);
      int atom_status_code = atom_result["status"].asInt();
      Json::Value atom_value = atom_result["value"];
      status_code = atom_status_code;
      *found_elements = atom_result["value"];
    } else {
      // Hitting a JavaScript error with the atom is an unrecoverable
      // error. The most common case of this for IE is when there is a
      // page refresh, navigation, or similar, and the driver is polling
      // for element presence. The calling code can't do anything about
      // it, so we might as well just log and return In the common case,
      // this means that the error will be transitory, and will sort
      // itself out once the DOM returns to normal after the page transition
      // is completed.
      LOG(WARN) << "A JavaScript error was encountered executing the findElements atom.";
    }
  } else {
    LOG(WARN) << "Unable to get browser";
  }
  return status_code;
}
예제 #11
0
bool RegistryUtilities::GetRegistryValue(const HKEY root_key,
                                         const std::wstring& subkey,
                                         const std::wstring& value_name,
                                         std::wstring *value) {
  std::string root_key_description = "HKEY_CURRENT_USER";
  if (root_key == HKEY_CLASSES_ROOT) {
    root_key_description = "HKEY_CLASSES_ROOT";
  } else if (root_key == HKEY_LOCAL_MACHINE) {
    root_key_description = "HKEY_LOCAL_MACHINE";
  }

  bool value_retrieved = false;
  DWORD required_buffer_size;
  DWORD value_type;
  HKEY key_handle;
  long registry_call_result = ::RegOpenKeyEx(root_key,
                                             subkey.c_str(),
                                             0,
                                             KEY_QUERY_VALUE,
                                             &key_handle);
  if (ERROR_SUCCESS == registry_call_result) {
    registry_call_result = ::RegQueryValueEx(key_handle,
                                             value_name.c_str(),
                                             NULL,
                                             &value_type,
                                             NULL,
                                             &required_buffer_size);
    if (ERROR_SUCCESS == registry_call_result) {
      if (value_type == REG_SZ || value_type == REG_EXPAND_SZ || value_type == REG_MULTI_SZ) {
        std::vector<wchar_t> value_buffer(required_buffer_size);
        registry_call_result = ::RegQueryValueEx(key_handle,
                                                value_name.c_str(),
                                                NULL,
                                                &value_type,
                                                reinterpret_cast<LPBYTE>(&value_buffer[0]),
                                                &required_buffer_size);
        if (ERROR_SUCCESS == registry_call_result) {
          *value = &value_buffer[0];
          value_retrieved = true;
        }
      } else if (value_type == REG_DWORD) {
        DWORD numeric_value = 0;
        registry_call_result = ::RegQueryValueEx(key_handle,
                                                 value_name.c_str(),
                                                 NULL,
                                                 &value_type,
                                                 reinterpret_cast<LPBYTE>(&numeric_value),
                                                 &required_buffer_size);
        if (ERROR_SUCCESS == registry_call_result) {
          // Coerce the numeric value to a string to return back.
          // Assume 10 characters will be enough to hold the size
          // of the value.
          std::vector<wchar_t> numeric_value_buffer(10);
          _ltow_s(numeric_value, &numeric_value_buffer[0], numeric_value_buffer.size(), 10);
          *value = &numeric_value_buffer[0];
          value_retrieved = true;
        }
      } else {
        LOG(WARN) << "Unexpected value type of " << value_type
                  << " for RegQueryValueEx was found for value with name "
                  << LOGWSTRING(value_name) << " in subkey "
                  << LOGWSTRING(subkey) << " in hive "
                  << root_key_description;
      }
      if (ERROR_SUCCESS != registry_call_result) {
        LOG(WARN) << "RegQueryValueEx failed with error code "
                  << registry_call_result << " retrieving value with name "
                  << LOGWSTRING(value_name) << " in subkey "
                  << LOGWSTRING(subkey) << "in hive "
                  << root_key_description;
      }
    } else {
      LOG(WARN) << "RegQueryValueEx failed with error code "
                << registry_call_result
                << " retrieving required buffer size for value with name "
                << LOGWSTRING(value_name) << " in subkey "
                << LOGWSTRING(subkey) << " in hive "
                << root_key_description;
    }
    ::RegCloseKey(key_handle);
  } else {
    LOG(WARN) << "RegOpenKeyEx failed with error code "
              << registry_call_result <<  " attempting to open subkey "
              << LOGWSTRING(subkey) << " in hive "
              << root_key_description;

  }
  return value_retrieved;
}
예제 #12
0
int ElementFinder::FindElement(const IECommandExecutor& executor,
                               const ElementHandle parent_wrapper,
                               const std::wstring& mechanism,
                               const std::wstring& criteria,
                               Json::Value* found_element) {
  LOG(TRACE) << "Entering ElementFinder::FindElement";

  BrowserHandle browser;
  int status_code = executor.GetCurrentBrowser(&browser);
  if (status_code == WD_SUCCESS) {
    if (mechanism == L"css") {
      if (!this->HasNativeCssSelectorEngine(executor)) {
        LOG(DEBUG) << "Element location strategy is CSS selectors, but "
                   << "document does not support CSS selectors. Falling back "
                   << "to using the Sizzle JavaScript CSS selector engine.";
        return this->FindElementUsingSizzle(executor,
                                            parent_wrapper,
                                            criteria,
                                            found_element);
      }
    }

    LOG(DEBUG) << L"Using FindElement atom to locate element having "
               << LOGWSTRING(mechanism) << " = "
               << LOGWSTRING(criteria);
    std::wstring sanitized_criteria = criteria;
    this->SanitizeCriteria(mechanism, &sanitized_criteria);
    std::wstring criteria_object_script = L"(function() { return function(){ return  { \"" + 
                                          mechanism + 
                                          L"\" : \"" +
                                          sanitized_criteria + L"\" }; };})();";
    CComPtr<IHTMLDocument2> doc;
    browser->GetDocument(&doc);

    Script criteria_wrapper(doc, criteria_object_script, 0);
    status_code = criteria_wrapper.Execute();
    if (status_code == WD_SUCCESS) {
      CComVariant criteria_object;
      criteria_object.Copy(&criteria_wrapper.result());

      // The atom is just the definition of an anonymous
      // function: "function() {...}"; Wrap it in another function so we can
      // invoke it with our arguments without polluting the current namespace.
      std::wstring script_source(L"(function() { return (");
      script_source += atoms::asString(atoms::FIND_ELEMENT);
      script_source += L")})();";

      Script script_wrapper(doc, script_source, 2);
      script_wrapper.AddArgument(criteria_object);
      if (parent_wrapper) {
        script_wrapper.AddArgument(parent_wrapper->element());
      }

      status_code = script_wrapper.Execute();
      if (status_code == WD_SUCCESS) {
        if (script_wrapper.ResultIsElement()) {
          script_wrapper.ConvertResultToJsonValue(executor, found_element);
        } else {
          LOG(WARN) << "Unable to find element by mechanism "
                    << LOGWSTRING(mechanism) << " and criteria " 
                    << LOGWSTRING(sanitized_criteria);
          status_code = ENOSUCHELEMENT;
        }
      } else {
        // An error in the execution of the FindElement atom for XPath is assumed
        // to be a syntactically invalid XPath.
        if (mechanism == L"xpath") {
          LOG(WARN) << "Attempted to find element using invalid xpath: "
                    << LOGWSTRING(sanitized_criteria);
          status_code = EINVALIDSELECTOR;
        } else {
          LOG(WARN) << "Unexpected error attempting to find element by mechanism "
                    << LOGWSTRING(mechanism) << " with criteria "
                    << LOGWSTRING(sanitized_criteria);
          status_code = ENOSUCHELEMENT;
        }
      }
    } else {
      LOG(WARN) << "Unable to create criteria object for mechanism "
                << LOGWSTRING(mechanism) << " and criteria " 
                << LOGWSTRING(sanitized_criteria);
      status_code = ENOSUCHELEMENT;
    }
  } else {
    LOG(WARN) << "Unable to get browser";
  }
  return status_code;
}
예제 #13
0
int ElementFinder::FindElements(const IECommandExecutor& executor,
                                const ElementHandle parent_wrapper,
                                const std::wstring& mechanism,
                                const std::wstring& criteria,
                                Json::Value* found_elements) {
  LOG(TRACE) << "Entering ElementFinder::FindElements";

  BrowserHandle browser;
  int status_code = executor.GetCurrentBrowser(&browser);
  if (status_code == WD_SUCCESS) {
    if (mechanism == L"css") {
      if (!this->HasNativeCssSelectorEngine(executor)) {
        LOG(DEBUG) << "Element location strategy is CSS selectors, but "
                   << "document does not support CSS selectors. Falling back "
                   << "to using the Sizzle JavaScript CSS selector engine.";
        return this->FindElementsUsingSizzle(executor,
                                             parent_wrapper,
                                             criteria,
                                             found_elements);
      }
    }

    LOG(DEBUG) << "Using FindElements atom to locate element having "
               << LOGWSTRING(mechanism) << " = "
               << LOGWSTRING(criteria);
    CComPtr<IHTMLDocument2> doc;
    browser->GetDocument(&doc);

    std::wstring script_source(L"(function() { return (");
    script_source += atoms::asString(atoms::FIND_ELEMENTS);
    script_source += L")})();";

    Script script_wrapper(doc, script_source, 3);
    script_wrapper.AddArgument(mechanism);
    script_wrapper.AddArgument(criteria);
    if (parent_wrapper) {
      script_wrapper.AddArgument(parent_wrapper->element());
    }

    status_code = script_wrapper.Execute();
    if (status_code == WD_SUCCESS) {
      if (script_wrapper.ResultIsArray() || 
          script_wrapper.ResultIsElementCollection()) {
        script_wrapper.ConvertResultToJsonValue(executor, found_elements);
      } else {
        LOG(WARN) << "Returned value is not an array or element collection";
        status_code = ENOSUCHELEMENT;
      }
    } else {
      // An error in the execution of the FindElement atom for XPath is assumed
      // to be a syntactically invalid XPath.
      if (mechanism == L"xpath") {
        LOG(WARN) << "Attempted to find elements using invalid xpath: "
                  << LOGWSTRING(criteria);
        status_code = EINVALIDSELECTOR;
      } else {
        LOG(WARN) << "Unexpected error attempting to find element by mechanism "
                  << LOGWSTRING(mechanism) << " and criteria "
                  << LOGWSTRING(criteria);
        status_code = ENOSUCHELEMENT;
      }
    }
  } else {
    LOG(WARN) << "Unable to get browser";
  }
  return status_code;
}