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();
}