// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "topaz/auth_providers/google/google_auth_provider_impl.h"

#include <fuchsia/net/oldhttp/cpp/fidl.h>
#include <lib/fdio/directory.h>
#include <lib/fit/function.h>
#include <lib/syslog/global.h>
#include <lib/ui/scenic/cpp/view_token_pair.h>

#include "garnet/public/lib/rapidjson_utils/rapidjson_validation.h"
#include "lib/component/cpp/connect.h"
#include "lib/component/cpp/startup_context.h"
#include "lib/fidl/cpp/interface_request.h"
#include "lib/svc/cpp/services.h"
#include "peridot/lib/rapidjson/rapidjson.h"
#include "rapidjson/document.h"
#include "rapidjson/schema.h"
#include "src/lib/fxl/strings/join_strings.h"
#include "topaz/auth_providers/google/constants.h"
#include "topaz/auth_providers/oauth/oauth_request_builder.h"
#include "topaz/auth_providers/oauth/oauth_response.h"

namespace google_auth_provider {

namespace http = ::fuchsia::net::oldhttp;

namespace {

constexpr char kInjectionEntry[] = "LegacyAuthCredentialInjector";

std::string GetClientId(const std::string& app_client_id) {
  // By default, use the client_id of the invoking application.
  std::string client_id = app_client_id;

  // Use hard-coded Fuchsia client_id for downscoped tokens, if |app_client_id|
  // is missing.
  if (app_client_id.empty()) {
    client_id = kFuchsiaClientId;
  }

  return client_id;
}

// Outputs information from a failing OAuthResponse to the syslog.
void LogOauthResponse(const char* operation,
                      const auth_providers::oauth::OAuthResponse& response) {
  FX_LOGF(WARNING, NULL,
          "OAuthResponse error during %s: %s (Full response: %s)", operation,
          response.error_description.c_str(),
          modular::JsonValueToPrettyString(response.json_response).c_str());
}

// Sometimes auth codes contain non alpha characters such as a slash. When we
// receive these in a url parameter they are Hex encoded, but they need to be
// translated back to UTF-8 before using the auth code.
//
// TODO(jsankey): Remove this once we migrate to cookie delivery, or use a
// common encoding/decoding library if that arrives earlier.
void NormalizeAuthCode(std::string* code) {
  // This function uses the following literals:
  //   1 - The length of '%'
  //   2 - The length of a hex byte, e.g. '2F'
  //   3 - The length of a %-prefixed hex byte, e.g. '%2F'
  //  16 - The base of hexadecimal
  //  32 - The smallest printable character, i.e. the space character
  // 127 - The largest single byte UTF-8 codepoint
  std::string::size_type pos = 0;
  while ((pos = code->find("%", pos)) != std::string::npos &&
         pos <= code->length() - 3) {
    int codepoint = strtol(code->substr(pos + 1, 2).c_str(), nullptr, 16);
    if (codepoint >= 33 && codepoint <= 127) {
      code->replace(pos, 3, std::string(1, codepoint));
    }
    pos += 3;
  }
}

// Checks the supplied Google authentication URL. If the URL indicated the user
// has aborted the flow or an error occured these are reported as error
// statuses, otherwise a status of OK is returned. If the URL contains an auth
// code query parameter, this will be returned in |auth_code|.
fuchsia::auth::AuthProviderStatus ParseAuthCodeFromUrl(const std::string& url,
                                                       std::string& auth_code) {
  static const std::string success_prefix =
      std::string{kRedirectUri} + "?code=";
  static const std::string cancel_prefix =
      std::string{kRedirectUri} + "?error=access_denied";

  if (url.find(cancel_prefix) == 0) {
    return fuchsia::auth::AuthProviderStatus::USER_CANCELLED;
  }
  if (url.find(success_prefix) != 0) {
    // The authentication process is still ongoing.
    return fuchsia::auth::AuthProviderStatus::OK;
  }

  // Take everything up to the next query parameter or hash fragment.
  auto end_char = url.find_first_of("#&", success_prefix.size());
  auto length = end_char == std::string::npos
                    ? std::string::npos
                    : end_char - success_prefix.size();
  auto code = url.substr(success_prefix.size(), length);
  NormalizeAuthCode(&code);

  if (code.empty()) {
    return fuchsia::auth::AuthProviderStatus::OAUTH_SERVER_ERROR;
  } else {
    auth_code = code;
    return fuchsia::auth::AuthProviderStatus::OK;
  }
}

}  // namespace

using auth_providers::oauth::OAuthRequestBuilder;
using auth_providers::oauth::ParseOAuthResponse;
using fuchsia::auth::AuthenticationUIContext;
using fuchsia::auth::AuthProviderStatus;
using fuchsia::auth::AuthTokenPtr;
using fuchsia::auth::FirebaseTokenPtr;
using modular::JsonValueToPrettyString;

GoogleAuthProviderImpl::GoogleAuthProviderImpl(
    async_dispatcher_t* const main_dispatcher,
    component::StartupContext* context,
    network_wrapper::NetworkWrapper* network_wrapper, Settings settings,
    fidl::InterfaceRequest<fuchsia::auth::AuthProvider> request)
    : main_dispatcher_(main_dispatcher),
      context_(context),
      network_wrapper_(network_wrapper),
      settings_(std::move(settings)),
      binding_(this, std::move(request)) {
  FXL_DCHECK(main_dispatcher_);
  FXL_DCHECK(network_wrapper_);

  // The class shuts down when the client connection is disconnected.
  binding_.set_error_handler([this](zx_status_t status) {
    if (on_empty_) {
      on_empty_();
    }
  });
}

GoogleAuthProviderImpl::~GoogleAuthProviderImpl() {}

void GoogleAuthProviderImpl::GetPersistentCredential(
    fidl::InterfaceHandle<AuthenticationUIContext> auth_ui_context,
    fidl::StringPtr user_profile_id, GetPersistentCredentialCallback callback) {
  FXL_DCHECK(auth_ui_context);
  get_persistent_credential_callback_ = std::move(callback);

  std::string url = GetAuthorizeUrl(user_profile_id);
  fuchsia::ui::views::ViewHolderToken view_holder_token = SetupChromium();
  if (!view_holder_token.value) {
    return;
  }
  chromium::web::NavigationControllerPtr controller;
  chromium_frame_->GetNavigationController(controller.NewRequest());
  controller->LoadUrl(url, chromium::web::LoadUrlParams());
  FX_LOGF(INFO, NULL, "Loading URL: %s", url.c_str());

  auth_ui_context_ = auth_ui_context.Bind();
  auth_ui_context_.set_error_handler([this](zx_status_t status) {
    FX_LOG(INFO, NULL, "Overlay cancelled by the caller");
    ReleaseResources();
    RemoveCredentialInjectorInterface();
    SafelyCallbackGetPersistentCredential(AuthProviderStatus::UNKNOWN_ERROR,
                                          nullptr, nullptr);
    return;
  });

  auth_ui_context_->StartOverlay2(std::move(view_holder_token.value));
  ExposeCredentialInjectorInterface();
}

void GoogleAuthProviderImpl::GetAppAccessToken(
    std::string credential, fidl::StringPtr app_client_id,
    const std::vector<std::string> app_scopes,
    GetAppAccessTokenCallback callback) {
  if (credential.empty()) {
    callback(AuthProviderStatus::BAD_REQUEST, nullptr);
    return;
  }

  auto request =
      OAuthRequestBuilder(kGoogleOAuthTokenEndpoint, "POST")
          .SetUrlEncodedBody("refresh_token=" + credential +
                             "&client_id=" + GetClientId(app_client_id.get()) +
                             "&grant_type=refresh_token");

  auto request_factory = [request = std::move(request)] {
    return request.Build();
  };

  Request(std::move(request_factory),
          [callback = std::move(callback)](http::URLResponse response) {
            auto oauth_response = ParseOAuthResponse(std::move(response));
            if (oauth_response.status != AuthProviderStatus::OK) {
              LogOauthResponse("GetAppAccessToken", oauth_response);
              callback(oauth_response.status, nullptr);
              return;
            }

            const char kRootSchema[] = R"({
              "type": "object",
              "properties": {
                "access_token": {
                  "type": "string"
                },
                "expires_in": {
                  "type": "integer"
                }
              },
              "required": ["access_token", "expires_in"]
            })";
            auto root_schema = rapidjson_utils::InitSchema(kRootSchema);
            if (!root_schema) {
              callback(AuthProviderStatus::INTERNAL_ERROR, nullptr);
              return;
            }
            if (!rapidjson_utils::ValidateSchema(oauth_response.json_response,
                                                 *root_schema)) {
              callback(AuthProviderStatus::OAUTH_SERVER_ERROR, nullptr);
              return;
            }

            AuthTokenPtr access_token = fuchsia::auth::AuthToken::New();
            access_token->token_type = fuchsia::auth::TokenType::ACCESS_TOKEN;
            access_token->token =
                oauth_response.json_response["access_token"].GetString();
            access_token->expires_in =
                oauth_response.json_response["expires_in"].GetUint64();

            callback(AuthProviderStatus::OK, std::move(access_token));
          });
}

void GoogleAuthProviderImpl::GetAppIdToken(std::string credential,
                                           fidl::StringPtr audience,
                                           GetAppIdTokenCallback callback) {
  if (credential.empty()) {
    callback(AuthProviderStatus::BAD_REQUEST, nullptr);
    return;
  }

  auto request =
      OAuthRequestBuilder(kGoogleOAuthTokenEndpoint, "POST")
          .SetUrlEncodedBody("refresh_token=" + credential +
                             "&client_id=" + GetClientId(audience.get()) +
                             "&grant_type=refresh_token");

  auto request_factory = [request = std::move(request)] {
    return request.Build();
  };
  Request(std::move(request_factory),
          [callback = std::move(callback)](http::URLResponse response) {
            auto oauth_response = ParseOAuthResponse(std::move(response));
            if (oauth_response.status != AuthProviderStatus::OK) {
              LogOauthResponse("GetAppIdToken", oauth_response);
              callback(oauth_response.status, nullptr);
              return;
            }

            const char kRootSchema[] = R"({
              "type": "object",
              "properties": {
                "id_token": {
                  "type": "string"
                },
                "expires_in": {
                  "type": "integer"
                }
              },
              "required": ["id_token", "expires_in"]
            })";
            auto root_schema = rapidjson_utils::InitSchema(kRootSchema);
            if (!root_schema) {
              callback(AuthProviderStatus::INTERNAL_ERROR, nullptr);
              return;
            }
            if (!rapidjson_utils::ValidateSchema(oauth_response.json_response,
                                                 *root_schema)) {
              callback(AuthProviderStatus::OAUTH_SERVER_ERROR, nullptr);
              return;
            }

            AuthTokenPtr id_token = fuchsia::auth::AuthToken::New();
            id_token->token =
                oauth_response.json_response["id_token"].GetString();
            id_token->token_type = fuchsia::auth::TokenType::ID_TOKEN;
            id_token->expires_in =
                oauth_response.json_response["expires_in"].GetUint64();

            callback(AuthProviderStatus::OK, std::move(id_token));
          });
}

void GoogleAuthProviderImpl::GetAppFirebaseToken(
    std::string id_token, std::string firebase_api_key,
    GetAppFirebaseTokenCallback callback) {
  if (id_token.empty() || firebase_api_key.empty()) {
    callback(AuthProviderStatus::BAD_REQUEST, nullptr);
    return;
  }

  std::map<std::string, std::string> query_params;
  query_params["key"] = firebase_api_key;
  auto request = OAuthRequestBuilder(kFirebaseAuthEndpoint, "POST")
                     .SetQueryParams(query_params)
                     .SetJsonBody(R"({"postBody": "id_token=)" + id_token +
                                  R"(&providerId=google.com",)" +
                                  R"("returnIdpCredential": true,)" +
                                  R"("returnSecureToken": true,)" +
                                  R"("requestUri": "http://localhost"})");

  // Exchange credential to access token at Google OAuth token endpoint
  auto request_factory = [request = std::move(request)] {
    return request.Build();
  };
  Request(std::move(request_factory), [callback = std::move(callback)](
                                          http::URLResponse response) {
    auto oauth_response = ParseOAuthResponse(std::move(response));
    if (oauth_response.status != AuthProviderStatus::OK) {
      LogOauthResponse("GetAppFirebaseToken", oauth_response);
      callback(oauth_response.status, nullptr);
      return;
    }

    const char kRootSchema[] = R"({
      "type": "object",
      "properties": {
        "idToken": {
          "type": "string"
        },
        "email": {
          "type": "string"
        },
        "localId": {
          "type": "string"
        },
        "expiresIn": {
          "type": "string"
        }
      },
      "required": ["idToken", "email", "localId", "expiresIn"]
    })";
    auto root_schema = rapidjson_utils::InitSchema(kRootSchema);
    if (!root_schema) {
      callback(AuthProviderStatus::INTERNAL_ERROR, nullptr);
      return;
    }
    if (!rapidjson_utils::ValidateSchema(oauth_response.json_response,
                                         *root_schema)) {
      callback(AuthProviderStatus::OAUTH_SERVER_ERROR, nullptr);
      return;
    }

    FirebaseTokenPtr fb_token = fuchsia::auth::FirebaseToken::New();
    fb_token->id_token = oauth_response.json_response["idToken"].GetString();
    fb_token->email = oauth_response.json_response["email"].GetString();
    fb_token->local_id = oauth_response.json_response["localId"].GetString();
    fb_token->expires_in =
        std::atoll(oauth_response.json_response["expiresIn"].GetString());

    callback(AuthProviderStatus::OK, std::move(fb_token));
  });
}

void GoogleAuthProviderImpl::RevokeAppOrPersistentCredential(
    std::string credential, RevokeAppOrPersistentCredentialCallback callback) {
  if (credential.empty()) {
    callback(AuthProviderStatus::BAD_REQUEST);
    return;
  }

  std::string url =
      kGoogleRevokeTokenEndpoint + std::string("?token=") + credential;
  auto request = OAuthRequestBuilder(url, "POST").SetUrlEncodedBody("");

  auto request_factory = [request = std::move(request)] {
    return request.Build();
  };

  Request(std::move(request_factory),
          [callback = std::move(callback)](http::URLResponse response) {
            auto oauth_response = ParseOAuthResponse(std::move(response));
            if (oauth_response.status != AuthProviderStatus::OK) {
              LogOauthResponse("RevokeToken", oauth_response);
              callback(oauth_response.status);
              return;
            }

            callback(AuthProviderStatus::OK);
          });
}

void GoogleAuthProviderImpl::GetPersistentCredentialFromAttestationJWT(
    fidl::InterfaceHandle<AttestationSigner> attestation_signer,
    AttestationJWTParams jwt_params,
    fidl::InterfaceHandle<AuthenticationUIContext> auth_ui_context,
    fidl::StringPtr user_profile_id,
    GetPersistentCredentialFromAttestationJWTCallback callback) {
  // Remote attestation flow not supported for traditional OAuth.
  callback(AuthProviderStatus::BAD_REQUEST, nullptr, nullptr, nullptr, nullptr);
}

void GoogleAuthProviderImpl::GetAppAccessTokenFromAssertionJWT(
    fidl::InterfaceHandle<AttestationSigner> attestation_signer,
    AssertionJWTParams jwt_params, std::string credential,
    const std::vector<std::string> scopes,
    GetAppAccessTokenFromAssertionJWTCallback callback) {
  // Remote attestation flow not supported for traditional OAuth.
  callback(AuthProviderStatus::BAD_REQUEST, nullptr, nullptr, nullptr);
}

void GoogleAuthProviderImpl::OnNavigationStateChanged(
    NavigationEvent change, OnNavigationStateChangedCallback callback) {
  // Not all events change the URL, those that don't can be ignored.
  if (change.url.is_null()) {
    callback();
    return;
  }

  std::string auth_code;
  AuthProviderStatus status = ParseAuthCodeFromUrl(change.url.get(), auth_code);

  // If either an error occured or the user successfully received an auth code
  // we need to close the browser instance.
  if (status != AuthProviderStatus::OK || !auth_code.empty()) {
    ReleaseResources();
    // InjectPersistentCredential will still be reachable even after removing
    // the interface from output, but any requests to it will be discarded.
    RemoveCredentialInjectorInterface();
    if (status != AuthProviderStatus::OK) {
      FX_LOGF(INFO, NULL, "Failed to capture auth code: Status %d", status);
      SafelyCallbackGetPersistentCredential(status, nullptr, nullptr);
    } else if (!auth_code.empty()) {
      FX_LOGF(INFO, NULL, "Captured auth code of length %d", auth_code.size());
      ExchangeAuthCode(auth_code);
    }
  }

  callback();
}

void GoogleAuthProviderImpl::InjectPersistentCredential(
    fuchsia::auth::UserProfileInfoPtr user_profile_info,
    std::string credential) {
  ReleaseResources();
  RemoveCredentialInjectorInterface();
  FX_LOGF(INFO, NULL, "Received injection request with credential of length %d",
          credential.size());
  SafelyCallbackGetPersistentCredential(AuthProviderStatus::OK,
                                        std::move(credential),
                                        std::move(user_profile_info));
}

std::string GoogleAuthProviderImpl::GetAuthorizeUrl(
    fidl::StringPtr user_profile) {
  // TODO(ukode,jsankey): use app_scopes instead of |kScopes|.
  const std::vector<std::string> scopes(kScopes.begin(), kScopes.end());
  std::string scopes_str = fxl::JoinStrings(scopes, "+");

  std::string url = settings_.use_dedicated_endpoint ? kGoogleFuchsiaEndpoint
                                                     : kGoogleOAuthAuthEndpoint;
  url += "?scope=" + scopes_str;
  url += "&glif=";
  url += settings_.use_glif ? "true" : "false";
  url += "&response_type=code&redirect_uri=";
  url += kRedirectUri;
  url += "&client_id=";
  url += kFuchsiaClientId;
  // TODO(ukode,jsankey): Set user_profile_id in the state query arg for re-auth
  // This probably involves moving the current implementation of UrlEncoding in
  // OAuthRequestBuilder to a reusable library and using this to urlencode the
  // supplied user_profile into the login_hint query parameter.
  return url;
}

void GoogleAuthProviderImpl::ExchangeAuthCode(std::string auth_code) {
  auto request = OAuthRequestBuilder(kGoogleOAuthTokenEndpoint, "POST")
                     .SetUrlEncodedBody("code=" + auth_code +
                                        "&redirect_uri=" + kRedirectUri +
                                        "&client_id=" + kFuchsiaClientId +
                                        "&grant_type=authorization_code");

  auto request_factory = [request = std::move(request)] {
    return request.Build();
  };

  Request(std::move(request_factory), [this](http::URLResponse response) {
    auto oauth_response = ParseOAuthResponse(std::move(response));
    if (oauth_response.status != AuthProviderStatus::OK) {
      LogOauthResponse("ExchangeAuthCode", oauth_response);
      SafelyCallbackGetPersistentCredential(oauth_response.status, nullptr,
                                            nullptr);
      return;
    }

    const char kRootSchema[] = R"({
      "type": "object",
      "properties": {
        "refresh_token": {
          "type": "string"
        },
        "access_token": {
          "type": "string"
        }
      },
      "required": ["refresh_token", "access_token"]
    })";
    auto root_schema = rapidjson_utils::InitSchema(kRootSchema);
    if (!root_schema) {
      SafelyCallbackGetPersistentCredential(AuthProviderStatus::INTERNAL_ERROR,
                                            nullptr, nullptr);
      return;
    }
    if (!rapidjson_utils::ValidateSchema(oauth_response.json_response,
                                         *root_schema)) {
      FX_LOGF(WARNING, NULL,
              "Got response without refresh and access tokens: %s",
              JsonValueToPrettyString(oauth_response.json_response).c_str());
      SafelyCallbackGetPersistentCredential(
          AuthProviderStatus::OAUTH_SERVER_ERROR, nullptr, nullptr);
      return;
    }

    auto refresh_token =
        oauth_response.json_response["refresh_token"].GetString();
    auto access_token =
        oauth_response.json_response["access_token"].GetString();
    FX_LOGF(INFO, NULL, "Received refresh token of length %d",
            strlen(refresh_token));

    GetUserProfile(refresh_token, access_token);
  });
}

void GoogleAuthProviderImpl::GetUserProfile(fidl::StringPtr credential,
                                            fidl::StringPtr access_token) {
  FXL_DCHECK(credential.get().size() > 0);
  FXL_DCHECK(access_token.get().size() > 0);

  auto request = OAuthRequestBuilder(kGoogleUserInfoEndpoint, "GET")
                     .SetAuthorizationHeader(access_token.get());

  auto request_factory = [request = std::move(request)] {
    return request.Build();
  };

  Request(std::move(request_factory), [this,
                                       credential](http::URLResponse response) {
    fuchsia::auth::UserProfileInfoPtr user_profile_info =
        fuchsia::auth::UserProfileInfo::New();

    auto oauth_response = ParseOAuthResponse(std::move(response));
    if (oauth_response.status != AuthProviderStatus::OK) {
      LogOauthResponse("UserInfo", oauth_response);
      SafelyCallbackGetPersistentCredential(oauth_response.status, credential,
                                            std::move(user_profile_info));
      return;
    }

    if (oauth_response.json_response.HasMember("sub") &&
        oauth_response.json_response["sub"].IsString()) {
      user_profile_info->id = oauth_response.json_response["sub"].GetString();
    } else {
      LogOauthResponse("UserInfo", oauth_response);
      FX_LOG(INFO, NULL, "Missing unique identifier in UserInfo response");
      SafelyCallbackGetPersistentCredential(
          AuthProviderStatus::OAUTH_SERVER_ERROR, nullptr,
          std::move(user_profile_info));
      return;
    }

    if (oauth_response.json_response.HasMember("name") &&
        oauth_response.json_response["name"].IsString()) {
      user_profile_info->display_name =
          oauth_response.json_response["name"].GetString();
    }

    if (oauth_response.json_response.HasMember("profile") &&
        oauth_response.json_response["profile"].IsString()) {
      user_profile_info->url =
          oauth_response.json_response["profile"].GetString();
    }

    if (oauth_response.json_response.HasMember("picture") &&
        oauth_response.json_response["picture"].IsString()) {
      user_profile_info->image_url =
          oauth_response.json_response["picture"].GetString();
    }

    FX_LOG(INFO, NULL, "Received valid UserInfo response");
    SafelyCallbackGetPersistentCredential(oauth_response.status, credential,
                                          std::move(user_profile_info));
  });
}

fuchsia::ui::views::ViewHolderToken GoogleAuthProviderImpl::SetupChromium() {
  // Connect to the Chromium service and create a new frame.
  auto context_provider =
      context_->ConnectToEnvironmentService<chromium::web::ContextProvider>();

  fidl::InterfaceHandle<fuchsia::io::Directory> incoming_service_clone =
      fidl::InterfaceHandle<fuchsia::io::Directory>(
          zx::channel(fdio_service_clone(
              context_->incoming_services()->directory().get())));
  if (!incoming_service_clone.is_valid()) {
    FX_LOG(ERROR, NULL, "Failed to clone service directory");
    return fuchsia::ui::views::ViewHolderToken();
  }

  chromium::web::CreateContextParams params;
  params.set_service_directory(std::move(incoming_service_clone));
  context_provider->Create(std::move(params), chromium_context_.NewRequest());
  chromium_context_->CreateFrame(chromium_frame_.NewRequest());

  // Bind ourselves as a NavigationEventObserver on this frame.
  chromium::web::NavigationEventObserverPtr navigation_event_observer;
  navigation_event_observer_bindings_.AddBinding(
      this, navigation_event_observer.NewRequest());
  chromium_frame_->SetNavigationEventObserver(
      std::move(navigation_event_observer));

  // And create a view for the frame.
  auto [view_token, view_holder_token] = scenic::NewViewTokenPair();
  chromium_frame_->CreateView(std::move(view_token));

  return std::move(view_holder_token);
}

void GoogleAuthProviderImpl::SafelyCallbackGetPersistentCredential(
    AuthProviderStatus auth_provider_status, fidl::StringPtr credential,
    fuchsia::auth::UserProfileInfoPtr user_profile_info) {
  if (get_persistent_credential_callback_) {
    get_persistent_credential_callback_(auth_provider_status,
                                        std::move(credential),
                                        std::move(user_profile_info));
    get_persistent_credential_callback_ = nullptr;
  } else {
    FX_LOG(WARNING, NULL,
           "Attempted to call GetPersistentCredential callback twice.");
  }
}

void GoogleAuthProviderImpl::ReleaseResources() {
  // Close any open view
  if (auth_ui_context_) {
    FX_LOG(INFO, NULL, "Releasing Auth UI Context");
    auth_ui_context_.set_error_handler(nullptr);
    auth_ui_context_->StopOverlay();
    auth_ui_context_ = nullptr;
  }
  // Release all smart pointers for Chromium resources.
  chromium_frame_ = nullptr;
  chromium_context_ = nullptr;
}

void GoogleAuthProviderImpl::ExposeCredentialInjectorInterface() {
  context_->outgoing().debug_dir()->AddEntry(
      kInjectionEntry,
      fbl::AdoptRef(new fs::Service([this](zx::channel channel) {
        fidl::InterfaceRequest<
            fuchsia::auth::testing::LegacyAuthCredentialInjector>
            request(std::move(channel));
        injector_bindings_.AddBinding(this, std::move(request));
        return ZX_OK;
      })));
}

void GoogleAuthProviderImpl::RemoveCredentialInjectorInterface() {
  if (context_->outgoing().debug_dir()->RemoveEntry(kInjectionEntry) ==
      ZX_ERR_NOT_FOUND) {
    FX_LOGF(WARNING, NULL,
            "Attempted to remove nonexistent '%s' from debug directory",
            kInjectionEntry);
  }
}

void GoogleAuthProviderImpl::Request(
    fit::function<http::URLRequest()> request_factory,
    fit::function<void(http::URLResponse response)> callback) {
  requests_.emplace(network_wrapper_->Request(std::move(request_factory),
                                              std::move(callback)));
}

}  // namespace google_auth_provider
