void InvitesReceiverInternalIos::FinishFetch()

in app/src/invites/ios/invites_receiver_internal_ios.mm [273:380]


void InvitesReceiverInternalIos::FinishFetch() {
  NSURL *url;
  NSString *source_application;
  id annotation;
  LinkType link_type;
  {
    MutexLock lock(g_static_mutex);
    FIREBASE_ASSERT(g_open_url != nil);
    // Consume the URL.
    url = g_open_url;
    g_open_url = nil;
    source_application = g_source_application;
    g_source_application = nil;
    annotation = g_annotation ? g_annotation : @{};  // handleURL fails on nil, use empty instead.
    g_annotation = nil;
    link_type = g_got_link_type;
    g_got_link_type = kLinkTypeNone;
  }

  if (link_type == kLinkTypeUrl) {
    LogDebug("URL link %s", url.absoluteString.UTF8String);
    // Regular URL, handle it synchronously.
    bool processed_link = false;
    LinkInfo link_info;
    {
      MutexLock lock(g_static_mutex);
      processed_link = g_callbacks && g_callbacks->FinishFetch(url, source_application, annotation,
                                                               &link_info);
    }

    int error_code = 0;
    const char* error_string = "";
    if (!processed_link) {
      // If FIRInvites couldn't get a link, check via FIRDynamicLinks instead (required for iOS 8).
      FIRDynamicLink *dynamicLink =
          [[FIRDynamicLinks dynamicLinks] dynamicLinkFromCustomSchemeURL:url];

      if (dynamicLink) {
        // Got a FIRDynamicLink. It may or may not have an inviteId, but it will have a link.
        // TODO(jsimantov): when FIRDynamicLink has metadata implemented, switch inviteId to use
        // that.
        NSString *inviteId = [dynamicLink inviteId];
        if (inviteId) link_info.invite_id = inviteId.UTF8String;
        if (dynamicLink.url) link_info.deep_link = [dynamicLink.url absoluteString].UTF8String;
        // TODO(jsimantov): Remove this workaround when b/27612427 is fixed.
        if (link_info.deep_link == InvitesReceiverInternalIos::kNullDeepLinkUrl) {
          link_info.deep_link = "";
        }
        link_info.match_strength = MatchTypeToLinkStrength(dynamicLink.matchType);
      } else {
        LogWarning("Failed to process %s", url.absoluteString.UTF8String);
        error_string = "Unable to retrieve link";
        error_code = 1;
      }
    }
    ReceivedInviteCallback(link_info.invite_id, link_info.deep_link, link_info.match_strength,
                           error_code, error_string);
  } else if (link_type == kLinkTypeUniversal) {
    LogDebug("Universal link %s", url.absoluteString.UTF8String);
    // Keep a strong reference to the FIRDynamicLinks singleton in the completion block until
    // the block is complete.
    __block FIRDynamicLinks* dynamic_links_reference = [FIRDynamicLinks dynamicLinks];
    // iOS 9+ Universal Link, handle asynchronously. (dynamic links only)
    BOOL handled = [dynamic_links_reference handleUniversalLink:url
                                                     completion:^(
                                                         FIRDynamicLink *_Nullable dynamic_link,
                                                         NSError *_Nullable error) {
                   MutexLock lock(g_static_mutex);
                   dynamic_links_reference = nil;
                   auto receiver = g_invites_receiver;
                   if (receiver) {
                     int error_code = 1; /* firebase::dynamic_links::kErrorCodeFailed */
                     std::string error_string = "Unknown error occurred.";
                     if (dynamic_link) {
                       std::string invite_id = util::NSStringToString(dynamic_link.inviteId);
                       std::string url_string = util::NSStringToString(
                           dynamic_link.url.absoluteString);
                       if (!url_string.empty() || !invite_id.empty()) {
                         receiver->ReceivedInviteCallback(
                             invite_id, url_string, MatchTypeToLinkStrength(dynamic_link.matchType),
                             0, "");
                         return;
                       }
                     }
                     if (error) {
                       std::string error_description =
                           util::NSStringToString(error.localizedDescription);
                       if (!error_description.empty()) error_string = error_description;
                       if (error.code) error_code = static_cast<int>(error.code);
                     } else {
                       error_string = "The short dynamic link references a scheme that does not "
                           "match this application's bundle ID.";
                     }
                     receiver->ReceivedInviteCallback("", "", kLinkMatchStrengthNoMatch, error_code,
                                                      error_string);
                   }
                 }];
    if (!handled) {
      // Link wasn't handled, complete with no received link.
      ReceivedInviteCallback("", "", kLinkMatchStrengthNoMatch, 0, "");
    }
  }
  {
    MutexLock lock(fetch_mutex_);
    fetch_in_progress_ = false;
  }
  callback_mutex_.Release();
}