1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "remoting/host/setup/win/auth_code_getter.h" 6 7 #include "base/strings/utf_string_conversions.h" 8 #include "base/time/time.h" 9 #include "base/win/scoped_bstr.h" 10 #include "base/win/scoped_variant.h" 11 #include "remoting/host/setup/oauth_helper.h" 12 13 namespace { 14 const int kUrlPollIntervalMs = 100; 15 } // namespace remoting 16 17 namespace remoting { 18 19 AuthCodeGetter::AuthCodeGetter() : 20 browser_(NULL), 21 timer_interval_(base::TimeDelta::FromMilliseconds(kUrlPollIntervalMs)) { 22 } 23 24 AuthCodeGetter::~AuthCodeGetter() { 25 KillBrowser(); 26 } 27 28 void AuthCodeGetter::GetAuthCode( 29 base::Callback<void(const std::string&)> on_auth_code) { 30 if (browser_) { 31 on_auth_code.Run(""); 32 return; 33 } 34 on_auth_code_ = on_auth_code; 35 HRESULT hr = browser_.CreateInstance(CLSID_InternetExplorer, NULL, 36 CLSCTX_LOCAL_SERVER); 37 if (FAILED(hr)) { 38 on_auth_code_.Run(""); 39 return; 40 } 41 base::win::ScopedBstr url(base::UTF8ToWide( 42 GetOauthStartUrl(GetDefaultOauthRedirectUrl())).c_str()); 43 base::win::ScopedVariant empty_variant; 44 hr = browser_->Navigate(url, empty_variant.AsInput(), empty_variant.AsInput(), 45 empty_variant.AsInput(), empty_variant.AsInput()); 46 if (FAILED(hr)) { 47 KillBrowser(); 48 on_auth_code_.Run(""); 49 return; 50 } 51 browser_->put_Visible(VARIANT_TRUE); 52 StartTimer(); 53 } 54 55 void AuthCodeGetter::StartTimer() { 56 timer_.Start(FROM_HERE, timer_interval_, this, &AuthCodeGetter::OnTimer); 57 } 58 59 void AuthCodeGetter::OnTimer() { 60 std::string auth_code; 61 if (TestBrowserUrl(&auth_code)) { 62 on_auth_code_.Run(auth_code); 63 } else { 64 StartTimer(); 65 } 66 } 67 68 bool AuthCodeGetter::TestBrowserUrl(std::string* auth_code) { 69 *auth_code = ""; 70 if (!browser_) { 71 return true; 72 } 73 base::win::ScopedBstr url; 74 HRESULT hr = browser_->get_LocationName(url.Receive()); 75 if (!SUCCEEDED(hr)) { 76 KillBrowser(); 77 return true; 78 } 79 *auth_code = GetOauthCodeInUrl(base::WideToUTF8(static_cast<BSTR>(url)), 80 GetDefaultOauthRedirectUrl()); 81 if (!auth_code->empty()) { 82 KillBrowser(); 83 return true; 84 } 85 return false; 86 } 87 88 void AuthCodeGetter::KillBrowser() { 89 if (browser_) { 90 browser_->Quit(); 91 browser_.Release(); 92 } 93 } 94 95 } // namespace remoting 96