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
13namespace {
14const int kUrlPollIntervalMs = 100;
15}  // namespace remoting
16
17namespace remoting {
18
19AuthCodeGetter::AuthCodeGetter() :
20    browser_(NULL),
21    timer_interval_(base::TimeDelta::FromMilliseconds(kUrlPollIntervalMs)) {
22}
23
24AuthCodeGetter::~AuthCodeGetter() {
25  KillBrowser();
26}
27
28void 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
55void AuthCodeGetter::StartTimer() {
56  timer_.Start(FROM_HERE, timer_interval_, this, &AuthCodeGetter::OnTimer);
57}
58
59void 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
68bool 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
88void AuthCodeGetter::KillBrowser() {
89  if (browser_) {
90    browser_->Quit();
91    browser_.Release();
92  }
93}
94
95}  // namespace remoting
96