Facebook.Unity.Editor/iOS/PListParser.cs (145 lines of code) (raw):

/** * Copyright (c) 2014-present, Facebook, Inc. All rights reserved. * * You are hereby granted a non-exclusive, worldwide, royalty-free license to use, * copy, modify, and distribute this software in source code or binary form for use * in connection with the web services and APIs provided by Facebook. * * As with any software that integrates with the Facebook platform, your use of * this software is subject to the Facebook Developer Principles and Policies * [http://developers.facebook.com/policy/]. This copyright notice shall be * included in all copies or substantial portions of the software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ namespace Facebook.Unity.Editor { using System; using System.Collections.Generic; using System.Text; using System.Xml; using System.Xml.Linq; using Facebook.Unity.Settings; internal class PListParser { private const string LSApplicationQueriesSchemesKey = "LSApplicationQueriesSchemes"; private const string CFBundleURLTypesKey = "CFBundleURLTypes"; private const string CFBundleURLSchemesKey = "CFBundleURLSchemes"; private const string CFBundleURLName = "CFBundleURLName"; private const string FacebookCFBundleURLName = "facebook-unity-sdk"; private const string FacebookAppIDKey = "FacebookAppID"; private const string FacebookAppIDPrefix = "fb"; private const string AutoLogAppEventsEnabled = "FacebookAutoLogAppEventsEnabled"; private const string AdvertiserIDCollectionEnabled = "FacebookAdvertiserIDCollectionEnabled"; private static readonly IList<object> FacebookLSApplicationQueriesSchemes = new List<object>() { "fbapi", "fb-messenger-api", "fbauth2", "fbshareextension" }; private static readonly PListDict FacebookUrlSchemes = new PListDict() { { PListParser.CFBundleURLName, PListParser.FacebookCFBundleURLName }, }; private string filePath; public PListParser(string fullPath) { this.filePath = fullPath; XmlReaderSettings settings = new XmlReaderSettings(); settings.ProhibitDtd = false; XmlReader plistReader = XmlReader.Create(this.filePath, settings); XDocument doc = XDocument.Load(plistReader); XElement plist = doc.Element("plist"); XElement dict = plist.Element("dict"); this.XMLDict = new PListDict(dict); plistReader.Close(); } public PListDict XMLDict { get; set; } public void UpdateFBSettings(string appID, string urlSuffix, ICollection<string> appLinkSchemes) { // Set the facbook app ID this.XMLDict[PListParser.FacebookAppIDKey] = appID; // Set the Auto Log AppEvents Enabled this.XMLDict[PListParser.AutoLogAppEventsEnabled] = FacebookSettings.AutoLogAppEventsEnabled; // Set the AdvertiserID Collection Enabled this.XMLDict[PListParser.AdvertiserIDCollectionEnabled] = FacebookSettings.AdvertiserIDCollectionEnabled; // Set the requried schemas for this app SetCFBundleURLSchemes(this.XMLDict, appID, urlSuffix, appLinkSchemes); // iOS 9+ Support WhitelistFacebookApps(this.XMLDict); } public void WriteToFile() { // Corrected header of the plist string publicId = "-//Apple//DTD PLIST 1.0//EN"; string stringId = "http://www.apple.com/DTDs/PropertyList-1.0.dtd"; string internalSubset = null; XDeclaration declaration = new XDeclaration("1.0", Encoding.UTF8.EncodingName, null); XDocumentType docType = new XDocumentType("plist", publicId, stringId, internalSubset); this.XMLDict.Save(this.filePath, declaration, docType); } private static void WhitelistFacebookApps(PListDict plistDict) { if (!ContainsKeyWithValueType(plistDict, PListParser.LSApplicationQueriesSchemesKey, typeof(IList<object>))) { // We don't have a LSApplicationQueriesSchemes entry. We can easily add one plistDict[PListParser.LSApplicationQueriesSchemesKey] = PListParser.FacebookLSApplicationQueriesSchemes; return; } var applicationQueriesSchemes = (IList<object>)plistDict[PListParser.LSApplicationQueriesSchemesKey]; foreach (var scheme in PListParser.FacebookLSApplicationQueriesSchemes) { if (!applicationQueriesSchemes.Contains(scheme)) { applicationQueriesSchemes.Add(scheme); } } } private static void SetCFBundleURLSchemes( PListDict plistDict, string appID, string urlSuffix, ICollection<string> appLinkSchemes) { IList<object> currentSchemas; if (ContainsKeyWithValueType(plistDict, PListParser.CFBundleURLTypesKey, typeof(IList<object>))) { currentSchemas = (IList<object>)plistDict[PListParser.CFBundleURLTypesKey]; } else { // Didn't find any CFBundleURLTypes, let's create one currentSchemas = new List<object>(); plistDict[PListParser.CFBundleURLTypesKey] = currentSchemas; } PListDict facebookBundleUrlSchemes = PListParser.GetFacebookUrlSchemes(currentSchemas); // Clear and set the CFBundleURLSchemes for the facebook schemes var facebookUrlSchemes = new List<object>(); facebookBundleUrlSchemes[PListParser.CFBundleURLSchemesKey] = facebookUrlSchemes; AddAppID(facebookUrlSchemes, appID, urlSuffix); AddAppLinkSchemes(facebookUrlSchemes, appLinkSchemes); } private static PListDict GetFacebookUrlSchemes(ICollection<object> plistSchemes) { foreach (var plistScheme in plistSchemes) { var bundleTypeNode = plistScheme as PListDict; if (bundleTypeNode != null) { // Check to see if the url scheme name is facebook string bundleURLName; if (bundleTypeNode.TryGetValue<string>(PListParser.CFBundleURLName, out bundleURLName) && bundleURLName == PListParser.FacebookCFBundleURLName) { return bundleTypeNode; } } } // We didn't find a facebook scheme so lets create one PListDict facebookUrlSchemes = new PListDict(PListParser.FacebookUrlSchemes); plistSchemes.Add(facebookUrlSchemes); return facebookUrlSchemes; } private static void AddAppID(ICollection<object> schemesCollection, string appID, string urlSuffix) { string modifiedID = PListParser.FacebookAppIDPrefix + appID; if (!string.IsNullOrEmpty(urlSuffix)) { modifiedID += urlSuffix; } schemesCollection.Add((object)modifiedID); } private static void AddAppLinkSchemes(ICollection<object> schemesCollection, ICollection<string> appLinkSchemes) { foreach (var appLinkScheme in appLinkSchemes) { schemesCollection.Add(appLinkScheme); } } private static bool ContainsKeyWithValueType(IDictionary<string, object> dictionary, string key, Type type) { if (dictionary.ContainsKey(key) && type.IsAssignableFrom(dictionary[key].GetType())) { return true; } return false; } } }