/// <summary>
        /// Adds a file specified by urls and version to downloads.
        /// </summary>
        /// <param name='urls'>
        /// An array of URLs (mirrors) to the same file. Download Manager would try
        /// to load file from them subsequently. End files MUST have the same name
        /// and extension, paths don't matter.
        /// </param>
        /// <param name='version'>
        /// Version of the file to download. If file with the specified version has
        /// been already downloaded, it would be loaded from the cache. Version might
        /// be positive integer value. If the file should be downloaded forcefully
        /// from the server, set version to VERSION_FORCE_REDOWNLOAD.
        /// </param>
        /// <param name='onDownloadCallback'>
        /// Function, which would be invoked once download be resolved. Set null, if
        /// no callback function should be executed.
        /// </param>
        public static Info LoadFromCacheOrDownloadAsync(string[] urls, int version, OnDownloadCallbackType onDownloadCallback)
        {
            Debug.Log("LoadFromCacheOrDownloadAsync - Started");
            Assertion.Check((urls != null) && (urls.Length > 0));
            foreach (string url in urls)
            {
                Assertion.Check(url.IndexOf("://") >= 0, "Protocol should be specified explicitly (\"file://\", \"http://\" etc.) for URL \"{0}\"", url);
            }

            // log urls
            string list = "";

            foreach (string url in urls)
            {
                list += string.Format("{0}{1}", string.IsNullOrEmpty(list) ? "" : "\n", url);
            }
            Debug.Log(string.Format("LoadFromCacheOrDownloadAsync - [in] urls:\n==>\n{0}\n<==", list));

            Info ret = null;

            if ((urls != null) && (urls.Length > 0))
            {
                for (int idx = 0; idx < urls.Length; ++idx)
                {
                    urls[idx] = urls[idx].Replace('\\', '/'); // prefers slash over backslash
                }

                Download download = FindDownloadByUrl(urls[0]);
                if (download == null)
                {
                    Debug.Log("LoadFromCacheOrDownloadAsync - Create new download");
                    download = new Download(urls, version, onDownloadCallback);
                    m_downloads.Add(download);
                    Debug.Log(string.Format("LoadFromCacheOrDownloadAsync - Added new download \"{0}\" to the list", urls[0]));
                }
                else
                {
                    Debug.LogWarning(string.Format("LoadFromCacheOrDownloadAsync - Download \"{0}\" is already requested", urls[0]));
                }

                ret = Info.Retrieve(download.GUID);
                EnsureDownloadCoroutines();
            }

            Assertion.Check(ret != null);
            if (ret == null)
            {
                Debug.LogWarning("LoadFromCacheOrDownloadAsync - Nothing to download");
            }

            Debug.Log("LoadFromCacheOrDownloadAsync - Finished");
            return(ret);
        }
 public Download(string[] urls, int version, OnDownloadCallbackType onDownloadCallback)
 {
     Debug.Log("Ctor - Started");
     m_guid = Guid.NewGuid().ToString();
     m_urls = new List <string>(urls.Length);
     m_urls.Clear();
     foreach (string url in urls)
     {
         m_urls.Add(url);
     }
     Assertion.Check((version == VERSION_FORCE_REDOWNLOAD) || (version >= 0)); // otherwise not implemented
     m_version            = version;
     m_onDownloadCallback = onDownloadCallback;
     m_www = null;
     m_offlineAssetBundle = null;
     m_state           = State.NotStarted;
     m_cacheStatus     = CacheStatus.Undefined;
     CurDownloadSource = DownloadSource.None;
     Debug.Log("Ctor - Finished");
 }