| 861 | } |
| 862 | |
| 863 | IWebBrowser2* BrowserFactory::CreateBrowser(bool is_protected_mode) { |
| 864 | LOG(TRACE) << "Entering BrowserFactory::CreateBrowser"; |
| 865 | |
| 866 | IWebBrowser2* browser = NULL; |
| 867 | DWORD context = CLSCTX_LOCAL_SERVER; |
| 868 | if (this->ie_major_version_ == 7 && IsWindowsVistaOrGreater()) { |
| 869 | // ONLY for IE 7 on Windows Vista. XP and below do not have Protected Mode; |
| 870 | // Windows 7 shipped with IE8. |
| 871 | context = context | CLSCTX_ENABLE_CLOAKING; |
| 872 | } |
| 873 | |
| 874 | HRESULT hr = S_OK; |
| 875 | if (is_protected_mode) { |
| 876 | hr = ::CoCreateInstance(CLSID_InternetExplorer, |
| 877 | NULL, |
| 878 | context, |
| 879 | IID_IWebBrowser2, |
| 880 | reinterpret_cast<void**>(&browser)); |
| 881 | } else { |
| 882 | hr = ::CoCreateInstance(CLSID_InternetExplorerMedium, |
| 883 | NULL, |
| 884 | context, |
| 885 | IID_IWebBrowser2, |
| 886 | reinterpret_cast<void**>(&browser)); |
| 887 | } |
| 888 | // When IWebBrowser2::Quit() is called, the wrapper process doesn't |
| 889 | // exit right away. When that happens, CoCreateInstance can fail while |
| 890 | // the abandoned iexplore.exe instance is still valid. The "right" way |
| 891 | // to do this would be to call ::EnumProcesses before calling |
| 892 | // CoCreateInstance, finding all of the iexplore.exe processes, waiting |
| 893 | // for one to exit, and then proceed. However, there is no way to tell |
| 894 | // if a process ID belongs to an Internet Explorer instance, particularly |
| 895 | // when a 32-bit process tries to enumerate 64-bit processes on 64-bit |
| 896 | // Windows. So, we'll take the brute force way out, just retrying the call |
| 897 | // to CoCreateInstance until it succeeds (the old iexplore.exe process has |
| 898 | // exited), or we get a different error code. We'll also set a 45-second |
| 899 | // timeout, with 45 seconds being chosen because it's below the default |
| 900 | // 60 second HTTP request timeout of most language bindings. |
| 901 | if (FAILED(hr) && HRESULT_CODE(hr) == ERROR_SHUTDOWN_IS_SCHEDULED) { |
| 902 | LOG(DEBUG) << "CoCreateInstance for IWebBrowser2 failed due to a " |
| 903 | << "browser process that has not yet fully exited. Retrying " |
| 904 | << "until the browser process exits and a new instance can " |
| 905 | << "be successfully created."; |
| 906 | } |
| 907 | clock_t timeout = clock() + (45 * CLOCKS_PER_SEC); |
| 908 | while (FAILED(hr) && |
| 909 | HRESULT_CODE(hr) == ERROR_SHUTDOWN_IS_SCHEDULED && |
| 910 | clock() < timeout) { |
| 911 | ::Sleep(500); |
| 912 | hr = ::CoCreateInstance(CLSID_InternetExplorer, |
| 913 | NULL, |
| 914 | context, |
| 915 | IID_IWebBrowser2, |
| 916 | reinterpret_cast<void**>(&browser)); |
| 917 | } |
| 918 | if (FAILED(hr) && HRESULT_CODE(hr) != ERROR_SHUTDOWN_IS_SCHEDULED) { |
| 919 | // If we hit this branch, the CoCreateInstance failed due to an unexpected |
| 920 | // error, either before we looped, or at some point during the loop. In |
no test coverage detected