├── .gitignore ├── css └── custom.style.css ├── index.html ├── js ├── OneDrive.Debug.js └── markdown-editor.js ├── license.txt ├── readme.md └── start-iis.bat /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | 84 | # Visual Studio profiler 85 | *.psess 86 | *.vsp 87 | *.vspx 88 | *.sap 89 | 90 | # TFS 2012 Local Workspace 91 | $tf/ 92 | 93 | # Guidance Automation Toolkit 94 | *.gpState 95 | 96 | # ReSharper is a .NET coding add-in 97 | _ReSharper*/ 98 | *.[Rr]e[Ss]harper 99 | *.DotSettings.user 100 | 101 | # JustCode is a .NET coding add-in 102 | .JustCode 103 | 104 | # TeamCity is a build add-in 105 | _TeamCity* 106 | 107 | # DotCover is a Code Coverage Tool 108 | *.dotCover 109 | 110 | # NCrunch 111 | _NCrunch_* 112 | .*crunch*.local.xml 113 | nCrunchTemp_* 114 | 115 | # MightyMoose 116 | *.mm.* 117 | AutoTest.Net/ 118 | 119 | # Web workbench (sass) 120 | .sass-cache/ 121 | 122 | # Installshield output folder 123 | [Ee]xpress/ 124 | 125 | # DocProject is a documentation generator add-in 126 | DocProject/buildhelp/ 127 | DocProject/Help/*.HxT 128 | DocProject/Help/*.HxC 129 | DocProject/Help/*.hhc 130 | DocProject/Help/*.hhk 131 | DocProject/Help/*.hhp 132 | DocProject/Help/Html2 133 | DocProject/Help/html 134 | 135 | # Click-Once directory 136 | publish/ 137 | 138 | # Publish Web Output 139 | *.[Pp]ublish.xml 140 | *.azurePubxml 141 | # TODO: Comment the next line if you want to checkin your web deploy settings 142 | # but database connection strings (with potential passwords) will be unencrypted 143 | *.pubxml 144 | *.publishproj 145 | 146 | # NuGet Packages 147 | *.nupkg 148 | # The packages folder can be ignored because of Package Restore 149 | **/packages/* 150 | # except build/, which is used as an MSBuild target. 151 | !**/packages/build/ 152 | # Uncomment if necessary however generally it will be regenerated when needed 153 | #!**/packages/repositories.config 154 | # NuGet v3's project.json files produces more ignoreable files 155 | *.nuget.props 156 | *.nuget.targets 157 | 158 | # Microsoft Azure Build Output 159 | csx/ 160 | *.build.csdef 161 | 162 | # Microsoft Azure Emulator 163 | ecf/ 164 | rcf/ 165 | 166 | # Microsoft Azure ApplicationInsights config file 167 | ApplicationInsights.config 168 | 169 | # Windows Store app package directory 170 | AppPackages/ 171 | BundleArtifacts/ 172 | 173 | # Visual Studio cache files 174 | # files ending in .cache can be ignored 175 | *.[Cc]ache 176 | # but keep track of directories ending in .cache 177 | !*.[Cc]ache/ 178 | 179 | # Others 180 | ClientBin/ 181 | ~$* 182 | *~ 183 | *.dbmdl 184 | *.dbproj.schemaview 185 | *.pfx 186 | *.publishsettings 187 | node_modules/ 188 | orleans.codegen.cs 189 | 190 | # RIA/Silverlight projects 191 | Generated_Code/ 192 | 193 | # Backup & report files from converting an old project file 194 | # to a newer Visual Studio version. Backup files are not needed, 195 | # because we have git ;-) 196 | _UpgradeReport_Files/ 197 | Backup*/ 198 | UpgradeLog*.XML 199 | UpgradeLog*.htm 200 | 201 | # SQL Server files 202 | *.mdf 203 | *.ldf 204 | 205 | # Business Intelligence projects 206 | *.rdl.data 207 | *.bim.layout 208 | *.bim_*.settings 209 | 210 | # Microsoft Fakes 211 | FakesAssemblies/ 212 | 213 | # GhostDoc plugin setting file 214 | *.GhostDoc.xml 215 | 216 | # Node.js Tools for Visual Studio 217 | .ntvs_analysis.dat 218 | 219 | # Visual Studio 6 build log 220 | *.plg 221 | 222 | # Visual Studio 6 workspace options file 223 | *.opt 224 | 225 | # Visual Studio LightSwitch build output 226 | **/*.HTMLClient/GeneratedArtifacts 227 | **/*.DesktopClient/GeneratedArtifacts 228 | **/*.DesktopClient/ModelManifest.xml 229 | **/*.Server/GeneratedArtifacts 230 | **/*.Server/ModelManifest.xml 231 | _Pvt_Extensions 232 | 233 | # Paket dependency manager 234 | .paket/paket.exe 235 | 236 | # FAKE - F# Make 237 | .fake/ 238 | -------------------------------------------------------------------------------- /css/custom.style.css: -------------------------------------------------------------------------------- 1 | body { 2 | height: 100%; 3 | } 4 | 5 | div.textEditor { 6 | position: absolute; 7 | left: 10px; 8 | right: 10px; 9 | width: auto; 10 | height: auto; 11 | top: 60px; 12 | bottom: 10px; 13 | box-sizing: border-box; 14 | -moz-box-sizing: border-box; 15 | -webkit-box-sizing: border-box; 16 | } 17 | 18 | textarea#canvas { 19 | font-family: Consolas; 20 | font-size: 12pt; 21 | width: 100%; 22 | height: 100%; 23 | box-sizing: border-box; 24 | -moz-box-sizing: border-box; 25 | -webkit-box-sizing: border-box; 26 | resize: none; 27 | } 28 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | OneDrive Markdown Editor Sample 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 28 | 29 | 30 |
31 |
32 | 63 |
64 | 65 | 66 |
67 | 68 | 69 |
70 | 71 | 72 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /js/OneDrive.Debug.js: -------------------------------------------------------------------------------- 1 | //! Copyright (c) Microsoft Corporation. All rights reserved. 2 | var __extends = (this && this.__extends) || function (d, b) {for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];function __() { this.constructor = d; }__.prototype = b.prototype;d.prototype = new __();}; 3 | (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.OneDrive = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o ACCESS_TOKEN_LIFESPAN; 593 | } 594 | exports.loginHintExpired = loginHintExpired; 595 | function updateLoginHint(clientId, idToken, invokerOptions) { 596 | var loginHint; 597 | var domainHint; 598 | var endpointHint; 599 | var apiEndpoint; 600 | switch (invokerOptions.endpointHint) { 601 | case DomainHint_1.default.aad: 602 | var idTokenObj = this.parseIdToken(idToken); 603 | loginHint = idTokenObj.preferredUserName; 604 | if (idTokenObj.tid === Constants_1.default.CUSTOMER_TID) { 605 | apiEndpoint = ApiEndpoint_1.default.graph_odc; 606 | domainHint = "consumers"; 607 | } else { 608 | apiEndpoint = ApiEndpoint_1.default.graph_odb; 609 | domainHint = "organizations"; 610 | } 611 | endpointHint = DomainHint_1.default.aad; 612 | break; 613 | case DomainHint_1.default.msa: 614 | apiEndpoint = ApiEndpoint_1.default.msa; 615 | endpointHint = DomainHint_1.default.msa; 616 | loginHint = invokerOptions.loginHint; 617 | domainHint = "consumers"; 618 | break; 619 | case DomainHint_1.default.tenant: 620 | apiEndpoint = ApiEndpoint_1.default.filesV2; 621 | endpointHint = DomainHint_1.default.tenant; 622 | loginHint = invokerOptions.loginHint; 623 | domainHint = "organizations"; 624 | break; 625 | } 626 | var newLoginHint = { 627 | apiEndpoint: apiEndpoint, 628 | loginHint: loginHint, 629 | domainHint: domainHint, 630 | endpointHint: endpointHint, 631 | timeStamp: new Date().getTime() 632 | }; 633 | var loginCache = Cache_1.getCacheItem(LOGINHINT_KEY) || {}; 634 | loginCache[LOGINHINT_ITEM_PREFIX + clientId] = newLoginHint; 635 | Cache_1.setCacheItem(LOGINHINT_KEY, loginCache); 636 | return newLoginHint; 637 | } 638 | exports.updateLoginHint = updateLoginHint; 639 | function parseIdToken(idToken) { 640 | if (!idToken) { 641 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.badResponse, 'id_token is missing in oauth response')); 642 | } 643 | var userInfoPart = idToken.split('.')[1]; 644 | var urlFriendlyValue = userInfoPart.replace('-', '+').replace('_', '/'); 645 | var userInfo = ObjectUtilities_1.deserializeJSON(atob(urlFriendlyValue)); 646 | if (!userInfo[ID_TOKEN_TID]) { 647 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.badResponse, 'tid is missing in id_token response')); 648 | } 649 | if (!userInfo[ID_TOKEN_PREFERRED_USERNAME]) { 650 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.badResponse, 'preferred_username is missing in id_token response')); 651 | } 652 | return { 653 | tid: userInfo[ID_TOKEN_TID], 654 | preferredUserName: userInfo[ID_TOKEN_PREFERRED_USERNAME] 655 | }; 656 | } 657 | exports.parseIdToken = parseIdToken; 658 | }(require, exports, require('../models/ApiEndpoint'), require('../utilities/Cache'), require('../Constants'), require('../models/DomainHint'), require('../utilities/ErrorHandler'), require('../models/ErrorType'), require('../models/OneDriveSdkError'), require('../utilities/ObjectUtilities'))); 659 | },{"../Constants":1,"../models/ApiEndpoint":11,"../models/DomainHint":12,"../models/ErrorType":13,"../models/OneDriveSdkError":16,"../utilities/Cache":22,"../utilities/ErrorHandler":26,"../utilities/ObjectUtilities":28}],7:[function(require,module,exports){ 660 | (function (require, exports, Channel_1, DomainHint_1, DomUtilities_1, ErrorHandler_1, ErrorType_1, LoginCache_1, OauthEndpoint_1, OneDriveSdkError_1, es6_promise_1, UrlUtilities_1) { 661 | 'use strict'; 662 | var PARAM_ACCESS_TOKEN = 'access_token'; 663 | var PARAM_ERROR = 'error'; 664 | var PARAM_ERROR_DESCRIPTION = 'error_description'; 665 | var PARAM_ID_TOKEN = 'id_token'; 666 | var PARAM_OAUTH_CONFIG = 'oauth'; 667 | var PARAM_STATE = 'state'; 668 | var AAD_OAUTH_ENDPOINT = 'https://login.microsoftonline.com/common/oauth2/authorize'; 669 | var AADV2_OAUTH_ENDPOINT = 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize'; 670 | var MSA_OAUTH_ENDPONT = 'https://login.live.com/oauth20_authorize.srf'; 671 | var OAUTH_RESPONSE_HEADER = '[OneDriveSDK-OauthResponse]'; 672 | function onAuth() { 673 | DomUtilities_1.onDocumentReady(function () { 674 | var redirResults = UrlUtilities_1.readCurrentUrlParameters(); 675 | var isOauth = redirResults[PARAM_OAUTH_CONFIG] || redirResults[PARAM_ERROR] || redirResults[PARAM_ACCESS_TOKEN]; 676 | if (isOauth && window.opener) { 677 | handleOauth(redirResults, new Channel_1.default(window.opener)); 678 | } 679 | }); 680 | } 681 | exports.onAuth = onAuth; 682 | function handleOauth(redirResults, channel) { 683 | DomUtilities_1.displayOverlay(); 684 | if (redirResults[PARAM_OAUTH_CONFIG]) { 685 | redirectToOauthPage(JSON.parse(redirResults[PARAM_OAUTH_CONFIG])); 686 | } else if (redirResults[PARAM_ERROR]) { 687 | sendResponseToParent(generateErrorResponse(redirResults), channel); 688 | } else if (redirResults[PARAM_ACCESS_TOKEN]) { 689 | sendResponseToParent(generateSuccessResponse(redirResults), channel); 690 | } 691 | } 692 | exports.handleOauth = handleOauth; 693 | function generateErrorResponse(redirResults) { 694 | var error = new OneDriveSdkError_1.default(ErrorType_1.default.badResponse, redirResults[PARAM_ERROR_DESCRIPTION]); 695 | return { 696 | type: 'error', 697 | error: error, 698 | state: redirResults[PARAM_STATE] 699 | }; 700 | } 701 | function generateSuccessResponse(redirResults) { 702 | return { 703 | type: 'success', 704 | accessToken: redirResults[PARAM_ACCESS_TOKEN], 705 | idToken: redirResults[PARAM_ID_TOKEN], 706 | state: redirResults[PARAM_STATE] 707 | }; 708 | } 709 | function sendResponseToParent(response, channel) { 710 | if (response.state) { 711 | var responseFragment = response.state.split('_'); 712 | if (responseFragment.length !== 2) { 713 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.badResponse, 'received bad state parameter from Oauth endpoint, state received: ' + response.state)).exposeToPublic(); 714 | } 715 | var origin = responseFragment[0]; 716 | if (channel) { 717 | channel.send(OAUTH_RESPONSE_HEADER + JSON.stringify(response), origin); 718 | } else { 719 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.popupOpen, 'opener is not defined')).exposeToPublic(); 720 | } 721 | } else { 722 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.badResponse, 'missing state parameter from Oauth redirect')).exposeToPublic(); 723 | } 724 | } 725 | function redirectToOauthPage(oauthConfig) { 726 | var url; 727 | switch (oauthConfig.endpoint) { 728 | case OauthEndpoint_1.default.AAD: 729 | url = buildAADOauthUrl(oauthConfig); 730 | break; 731 | case OauthEndpoint_1.default.AADv2: 732 | url = buildAADOauthV2Url(oauthConfig); 733 | break; 734 | case OauthEndpoint_1.default.MSA: 735 | url = buildMSAOauthUrl(oauthConfig); 736 | break; 737 | default: 738 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.badResponse, 'received bad oauth endpoint, endpoint value is: ' + oauthConfig.endpoint)); 739 | break; 740 | } 741 | if (oauthConfig.switchAccount) { 742 | url = UrlUtilities_1.appendQueryString(url, 'prompt', 'select_account'); 743 | } else if (oauthConfig.loginHint) { 744 | url = UrlUtilities_1.appendQueryString(url, 'login_hint', oauthConfig.loginHint); 745 | if (oauthConfig.domainHint) { 746 | url = UrlUtilities_1.appendQueryString(url, 'domain_hint', oauthConfig.domainHint); 747 | } 748 | } 749 | 750 | UrlUtilities_1.redirect(url); 751 | } 752 | function buildAADOauthUrl(config) { 753 | return UrlUtilities_1.appendQueryStrings(AAD_OAUTH_ENDPOINT, { 754 | redirect_uri: config.redirectUri, 755 | client_id: config.clientId, 756 | response_type: 'token', 757 | state: config.state, 758 | resource: config.origin 759 | }); 760 | } 761 | function buildAADOauthV2Url(config) { 762 | var scope = 'profile openid https://graph.microsoft.com/User.Read ' + config.scopes.map(function (s) { 763 | return 'https://graph.microsoft.com/' + s; 764 | }).join(' '); 765 | var url = UrlUtilities_1.appendQueryStrings(AADV2_OAUTH_ENDPOINT, { 766 | redirect_uri: config.redirectUri, 767 | client_id: config.clientId, 768 | scope: scope, 769 | response_mode: 'fragment', 770 | state: config.state, 771 | nonce: UrlUtilities_1.generateNonce() 772 | }); 773 | url += '&response_type=id_token+token'; 774 | return url; 775 | } 776 | function buildMSAOauthUrl(config) { 777 | var needWritePermission = false; 778 | for (var _i = 0, _a = config.scopes; _i < _a.length; _i++) { 779 | var scope = _a[_i]; 780 | needWritePermission = needWritePermission || scope.toLowerCase().indexOf('readwrite') > 1; 781 | } 782 | return UrlUtilities_1.appendQueryStrings(MSA_OAUTH_ENDPONT, { 783 | redirect_uri: config.redirectUri, 784 | client_id: config.clientId, 785 | response_type: 'token', 786 | state: config.state, 787 | scope: 'onedrive.' + (needWritePermission ? 'readwrite' : 'readonly') 788 | }); 789 | } 790 | function auth(config, popupView) { 791 | var state = document.location.origin + '_' + UrlUtilities_1.generateNonce(); 792 | config.state = state; 793 | return new es6_promise_1.Promise(function (resolve, reject) { 794 | var listenerId = DomUtilities_1.onMessage(function (event) { 795 | if (event.data && event.data.indexOf(OAUTH_RESPONSE_HEADER) === 0) { 796 | var responseData = JSON.parse(event.data.substring(OAUTH_RESPONSE_HEADER.length)); 797 | if (responseData.state === state && event.source === popupView.getPopupWindow()) { 798 | DomUtilities_1.removeMessageListener(listenerId); 799 | if (responseData.type === 'error' || responseData.error) { 800 | var errorCode = ErrorType_1.default[responseData.error.errorCode]; 801 | reject(new OneDriveSdkError_1.default(errorCode, responseData.error.message)); 802 | } else { 803 | resolve(responseData); 804 | } 805 | } else { 806 | reject(new OneDriveSdkError_1.default(ErrorType_1.default.popupOpen, 'Another popup is already opened.')); 807 | } 808 | } 809 | }); 810 | return popupView.openPopup(config.redirectUri + '?' + PARAM_OAUTH_CONFIG + '=' + JSON.stringify(config)).then(function () { 811 | resolve({ 812 | type: 'cancel', 813 | state: state 814 | }); 815 | }); 816 | }); 817 | } 818 | exports.auth = auth; 819 | function buildOauthConfig(invokerOptions, switchAccount) { 820 | var endpoint; 821 | switch (invokerOptions.endpointHint) { 822 | case DomainHint_1.default.aad: 823 | endpoint = OauthEndpoint_1.default.AADv2; 824 | break; 825 | case DomainHint_1.default.msa: 826 | endpoint = OauthEndpoint_1.default.MSA; 827 | break; 828 | case DomainHint_1.default.tenant: 829 | endpoint = OauthEndpoint_1.default.AAD; 830 | break; 831 | } 832 | var loginHint = LoginCache_1.getLoginHint(invokerOptions); 833 | var scopes = invokerOptions.scopes.map(function (s) { 834 | return s + (s.indexOf('Files.') > -1 && invokerOptions.needSharePointPermission ? '.All' : ''); 835 | }); 836 | return { 837 | clientId: invokerOptions.clientId, 838 | endpoint: endpoint, 839 | scopes: scopes, 840 | loginHint: invokerOptions.loginHint || (loginHint ? loginHint.loginHint : null), 841 | domainHint: invokerOptions.domainHint || (loginHint ? loginHint.domainHint : null), 842 | origin: window.location.origin, 843 | redirectUri: invokerOptions.redirectUri, 844 | switchAccount: switchAccount 845 | }; 846 | } 847 | exports.buildOauthConfig = buildOauthConfig; 848 | }(require, exports, require('../utilities/Channel'), require('../models/DomainHint'), require('../utilities/DomUtilities'), require('../utilities/ErrorHandler'), require('../models/ErrorType'), require('./LoginCache'), require('../models/OauthEndpoint'), require('../models/OneDriveSdkError'), require('es6-promise'), require('../utilities/UrlUtilities'))); 849 | },{"../models/DomainHint":12,"../models/ErrorType":13,"../models/OauthEndpoint":15,"../models/OneDriveSdkError":16,"../utilities/Channel":24,"../utilities/DomUtilities":25,"../utilities/ErrorHandler":26,"../utilities/UrlUtilities":32,"./LoginCache":6,"es6-promise":34}],8:[function(require,module,exports){ 850 | (function (require, exports, ApiEndpoint_1, ApiRequest_1, Constants_1, Invoker_1, ObjectUtilities_1, PickerOptions_1, PickerActionType_1, StringUtilities_1, UrlUtilities_1) { 851 | 'use strict'; 852 | var Picker = function (_super) { 853 | __extends(Picker, _super); 854 | function Picker(options) { 855 | var clonedOptions = ObjectUtilities_1.shallowClone(options); 856 | var pickerOptions = new PickerOptions_1.default(clonedOptions); 857 | _super.call(this, pickerOptions); 858 | } 859 | Picker.prototype.launchPicker = function () { 860 | return _super.prototype.launchInvoker.call(this); 861 | }; 862 | Picker.prototype.buildPickerUXConfig = function (pickerOptions) { 863 | var pickerUXConfig = { 864 | applicationId: pickerOptions.clientId, 865 | accessLevel: Picker.ACCESS_LEVEL, 866 | filter: pickerOptions.filter, 867 | id: UrlUtilities_1.generateNonce(), 868 | navEnabled: pickerOptions.navEnabled, 869 | origin: window.location.origin, 870 | parentDiv: pickerOptions.parentDiv, 871 | redirectUri: pickerOptions.redirectUri, 872 | selectionMode: pickerOptions.multiSelect ? 'multiple' : 'single', 873 | viewType: Picker.VIEW_TYPE 874 | }; 875 | return pickerUXConfig; 876 | }; 877 | Picker.prototype.makeApiRequest = function (files) { 878 | if (this.invokerOptions.action === PickerActionType_1.default.share) { 879 | return this.shareItems(files); 880 | } else { 881 | var isDownload = this.invokerOptions.action === PickerActionType_1.default.download; 882 | return this.queryItems(files, isDownload); 883 | } 884 | }; 885 | Picker.prototype.queryItems = function (files, isDownload) { 886 | var itemQuery = this.invokerOptions.queryParameters || Constants_1.default.DEFAULT_QUERY_ITEM_PARAMETER; 887 | if (isDownload) { 888 | itemQuery = StringUtilities_1.format('{0}{1}{2}', itemQuery, itemQuery.indexOf('select') === -1 ? '&select=' : ',', 'name,size,@content.downloadUrl'); 889 | } 890 | return ApiRequest_1.getItems(files, this.getApiRequestConfig(), itemQuery); 891 | }; 892 | Picker.prototype.shareItems = function (files) { 893 | var _this = this; 894 | var pickerOptions = this.invokerOptions; 895 | var createLinkParameters = pickerOptions.createLinkParameters || this.getDefaultSharingConfig(); 896 | return ApiRequest_1.getItems(files, this.getApiRequestConfig()).then(function (files) { 897 | return ApiRequest_1.shareItems(files, _this.getApiRequestConfig(), createLinkParameters); 898 | }); 899 | }; 900 | Picker.prototype.getDefaultSharingConfig = function () { 901 | var createLinkParameters = { 'type': 'view' }; 902 | if (this.getApiRequestConfig().apiEndpoint === ApiEndpoint_1.default.graph_odc || this.getApiRequestConfig().apiEndpoint === ApiEndpoint_1.default.msa) { 903 | return createLinkParameters; 904 | } 905 | createLinkParameters['scope'] = 'organization'; 906 | return createLinkParameters; 907 | }; 908 | Picker.ACCESS_LEVEL = 'read'; 909 | Picker.VIEW_TYPE = 'files'; 910 | return Picker; 911 | }(Invoker_1.default); 912 | Object.defineProperty(exports, '__esModule', { value: true }); 913 | exports.default = Picker; 914 | }(require, exports, require('../models/ApiEndpoint'), require('./ApiRequest'), require('../Constants'), require('./Invoker'), require('../utilities/ObjectUtilities'), require('../models/PickerOptions'), require('../models/PickerActionType'), require('../utilities/StringUtilities'), require('../utilities/UrlUtilities'))); 915 | },{"../Constants":1,"../models/ApiEndpoint":11,"../models/PickerActionType":17,"../models/PickerOptions":18,"../utilities/ObjectUtilities":28,"../utilities/StringUtilities":30,"../utilities/UrlUtilities":32,"./ApiRequest":4,"./Invoker":5}],9:[function(require,module,exports){ 916 | (function (require, exports, ApiEndpoint_1, Channel_1, DomUtilities_1, ErrorHandler_1, ErrorType_1, Logging_1, OneDriveSdkError_1, UrlUtilities_1, es6_promise_1, Constants_1) { 917 | 'use strict'; 918 | var CUSTOMER_PICKER_BASE_URL = 'https://onedrive.live.com/'; 919 | var RESPONSE_PREFIX = '[OneDrive-FromPicker]'; 920 | var MESSAGE_PREFIX = '[OneDrive-ToPicker]'; 921 | var INITIALIZE_RESPONSE = 'initialize'; 922 | function generatePickerUX(apiEndpoint, tenantUrl) { 923 | return new PickerUX(apiEndpoint, tenantUrl); 924 | } 925 | exports.generatePickerUX = generatePickerUX; 926 | var PickerUX = function () { 927 | function PickerUX(apiEndpoint, tenantUrl) { 928 | if (apiEndpoint === ApiEndpoint_1.default.graph_odc || apiEndpoint === ApiEndpoint_1.default.msa) { 929 | this.url = UrlUtilities_1.appendQueryStrings(CUSTOMER_PICKER_BASE_URL, { 'v': '2' }); 930 | } else if (apiEndpoint === ApiEndpoint_1.default.graph_odb || apiEndpoint === ApiEndpoint_1.default.filesV2) { 931 | if (!tenantUrl) { 932 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.optionsError, 'the site url must be specified')).exposeToPublic(); 933 | } 934 | UrlUtilities_1.validateUrlProtocol(tenantUrl, ['HTTPS']); 935 | if (apiEndpoint === ApiEndpoint_1.default.graph_odb) { 936 | tenantUrl = UrlUtilities_1.appendToPath(tenantUrl, '_layouts/onedrive.aspx'); 937 | } 938 | this.url = UrlUtilities_1.appendQueryString(tenantUrl, 'p', '2'); 939 | } 940 | } 941 | PickerUX.prototype.invokePickerUX = function (uxConfig, popupView) { 942 | var _this = this; 943 | var receivedResponse = false; 944 | var pickerUXPromise = new es6_promise_1.Promise(function (resolve, reject) { 945 | var channelId = DomUtilities_1.onMessage(function (event) { 946 | var urlParts = _this.url.split('/'); 947 | var channel = new Channel_1.default(_this.iframe ? _this.iframe.contentWindow : popupView.getPopupWindow()); 948 | if (event.origin === urlParts[0] + '//' + urlParts[2]) { 949 | var message = '' + (event.data || ''); 950 | if (message.indexOf(RESPONSE_PREFIX) === 0 && event.source === channel.getReceiver()) { 951 | var response = JSON.parse(message.substring(RESPONSE_PREFIX.length)); 952 | var pickerId = response.pickerId, conversationId = response.conversationId, type = response.type; 953 | if (pickerId === uxConfig.id) { 954 | if (type === INITIALIZE_RESPONSE) { 955 | channel.send(MESSAGE_PREFIX + JSON.stringify({ 956 | pickerId: pickerId, 957 | conversationId: conversationId, 958 | type: 'activate' 959 | }), event.origin); 960 | } else { 961 | receivedResponse = true; 962 | resolve(response); 963 | DomUtilities_1.removeMessageListener(channelId); 964 | } 965 | } 966 | } else { 967 | reject(new OneDriveSdkError_1.default(ErrorType_1.default.badResponse, 'received invalid response from picker UI')); 968 | } 969 | } 970 | }); 971 | var pickerOption = { 972 | aid: uxConfig.applicationId, 973 | a: uxConfig.accessLevel, 974 | id: uxConfig.id, 975 | l: uxConfig.linkType, 976 | ln: uxConfig.navEnabled, 977 | s: uxConfig.selectionMode, 978 | f: uxConfig.filter, 979 | v: uxConfig.viewType, 980 | ru: uxConfig.redirectUri, 981 | o: uxConfig.origin, 982 | sdk: Constants_1.default.SDK_VERSION_NUMBER, 983 | e: uxConfig.entryLocation, 984 | st: uxConfig.sourceTypes, 985 | sn: !uxConfig.parentDiv, 986 | ss: !uxConfig.parentDiv 987 | }; 988 | var pickerUrl = UrlUtilities_1.appendQueryString(_this.url, 'picker', JSON.stringify(pickerOption)); 989 | Logging_1.default.logMessage('invoke picker with url: ' + pickerUrl); 990 | if (uxConfig.parentDiv) { 991 | popupView.close(); 992 | var iframe = document.createElement('iframe'); 993 | iframe.id = 'odpicker' + new Date().getTime(); 994 | iframe.style.position = 'relative'; 995 | iframe.style.width = '100%'; 996 | iframe.style.height = '100%'; 997 | iframe.src = pickerUrl; 998 | uxConfig.parentDiv.appendChild(iframe); 999 | _this.iframe = iframe; 1000 | } else { 1001 | return popupView.openPopup(pickerUrl).then(function () { 1002 | resolve({ type: 'cancel' }); 1003 | }); 1004 | } 1005 | }); 1006 | return pickerUXPromise; 1007 | }; 1008 | PickerUX.prototype.removeIFrame = function () { 1009 | if (this.iframe) { 1010 | this.iframe.parentNode.removeChild(this.iframe); 1011 | this.iframe = null; 1012 | } 1013 | }; 1014 | return PickerUX; 1015 | }(); 1016 | Object.defineProperty(exports, '__esModule', { value: true }); 1017 | exports.default = PickerUX; 1018 | }(require, exports, require('../models/ApiEndpoint'), require('../utilities/Channel'), require('../utilities/DomUtilities'), require('../utilities/ErrorHandler'), require('../models/ErrorType'), require('../utilities/Logging'), require('../models/OneDriveSdkError'), require('../utilities/UrlUtilities'), require('es6-promise'), require('../Constants'))); 1019 | },{"../Constants":1,"../models/ApiEndpoint":11,"../models/ErrorType":13,"../models/OneDriveSdkError":16,"../utilities/Channel":24,"../utilities/DomUtilities":25,"../utilities/ErrorHandler":26,"../utilities/Logging":27,"../utilities/UrlUtilities":32,"es6-promise":34}],10:[function(require,module,exports){ 1020 | (function (require, exports, ApiRequest_1, Constants_1, Invoker_1, ObjectUtilities_1, SaverActionType_1, SaverOptions_1, UploadType_1, UrlUtilities_1) { 1021 | 'use strict'; 1022 | var ACCESS_LEVEL = 'readwrite'; 1023 | var VIEW_TYPE = 'folders'; 1024 | var SELECTION_MODE = 'single'; 1025 | var Saver = function (_super) { 1026 | __extends(Saver, _super); 1027 | function Saver(options) { 1028 | var clonedOptions = ObjectUtilities_1.shallowClone(options); 1029 | var saverOptions = new SaverOptions_1.default(clonedOptions); 1030 | _super.call(this, saverOptions); 1031 | } 1032 | Saver.prototype.launchSaver = function () { 1033 | return _super.prototype.launchInvoker.call(this); 1034 | }; 1035 | Saver.prototype.buildPickerUXConfig = function (saverOptions) { 1036 | return { 1037 | applicationId: saverOptions.clientId, 1038 | accessLevel: ACCESS_LEVEL, 1039 | id: UrlUtilities_1.generateNonce(), 1040 | navEnabled: saverOptions.navEnabled, 1041 | filter: saverOptions.filter, 1042 | origin: window.location.origin, 1043 | parentDiv: saverOptions.parentDiv, 1044 | redirectUri: saverOptions.redirectUri, 1045 | selectionMode: SELECTION_MODE, 1046 | viewType: VIEW_TYPE 1047 | }; 1048 | }; 1049 | Saver.prototype.makeApiRequest = function (files) { 1050 | var saverOptions = this.invokerOptions; 1051 | if (this.invokerOptions.action === SaverActionType_1.default.query) { 1052 | var itemQuery = this.invokerOptions.queryParameters || Constants_1.default.DEFAULT_QUERY_ITEM_PARAMETER; 1053 | return ApiRequest_1.getItems(files, this.apiRequestConfig, itemQuery); 1054 | } else if (saverOptions.uploadType === UploadType_1.default.dataUrl || saverOptions.uploadType === UploadType_1.default.url) { 1055 | var uploadItemDescription = { name: saverOptions.fileName }; 1056 | return ApiRequest_1.saveItemByUriUpload(files.value[0], uploadItemDescription, saverOptions.sourceUri, this.apiRequestConfig); 1057 | } else if (saverOptions.uploadType === UploadType_1.default.form) { 1058 | var uploadItemDescription = { 1059 | name: saverOptions.fileName, 1060 | '@name.conflictBehavior': saverOptions.nameConflictBehavior 1061 | }; 1062 | return ApiRequest_1.saveItemByFormUpload(files.value[0], uploadItemDescription, saverOptions.fileInput, this.apiRequestConfig, saverOptions.progress); 1063 | } 1064 | }; 1065 | return Saver; 1066 | }(Invoker_1.default); 1067 | Object.defineProperty(exports, '__esModule', { value: true }); 1068 | exports.default = Saver; 1069 | }(require, exports, require('./ApiRequest'), require('../Constants'), require('./Invoker'), require('../utilities/ObjectUtilities'), require('../models/SaverActionType'), require('../models/SaverOptions'), require('../models/UploadType'), require('../utilities/UrlUtilities'))); 1070 | },{"../Constants":1,"../models/SaverActionType":19,"../models/SaverOptions":20,"../models/UploadType":21,"../utilities/ObjectUtilities":28,"../utilities/UrlUtilities":32,"./ApiRequest":4,"./Invoker":5}],11:[function(require,module,exports){ 1071 | (function (require, exports) { 1072 | 'use strict'; 1073 | var ApiEndpoint; 1074 | (function (ApiEndpoint) { 1075 | ApiEndpoint[ApiEndpoint['filesV2'] = 0] = 'filesV2'; 1076 | ApiEndpoint[ApiEndpoint['graph_odc'] = 1] = 'graph_odc'; 1077 | ApiEndpoint[ApiEndpoint['graph_odb'] = 2] = 'graph_odb'; 1078 | ApiEndpoint[ApiEndpoint['msa'] = 3] = 'msa'; 1079 | }(ApiEndpoint || (ApiEndpoint = {}))); 1080 | Object.defineProperty(exports, '__esModule', { value: true }); 1081 | exports.default = ApiEndpoint; 1082 | }(require, exports)); 1083 | },{}],12:[function(require,module,exports){ 1084 | (function (require, exports) { 1085 | 'use strict'; 1086 | var DomainHint; 1087 | (function (DomainHint) { 1088 | DomainHint[DomainHint['aad'] = 0] = 'aad'; 1089 | DomainHint[DomainHint['msa'] = 1] = 'msa'; 1090 | DomainHint[DomainHint['tenant'] = 2] = 'tenant'; 1091 | }(DomainHint || (DomainHint = {}))); 1092 | Object.defineProperty(exports, '__esModule', { value: true }); 1093 | exports.default = DomainHint; 1094 | }(require, exports)); 1095 | },{}],13:[function(require,module,exports){ 1096 | (function (require, exports) { 1097 | 'use strict'; 1098 | var ErrorType; 1099 | (function (ErrorType) { 1100 | ErrorType[ErrorType['badResponse'] = 0] = 'badResponse'; 1101 | ErrorType[ErrorType['fileReaderFailure'] = 1] = 'fileReaderFailure'; 1102 | ErrorType[ErrorType['popupOpen'] = 2] = 'popupOpen'; 1103 | ErrorType[ErrorType['unknown'] = 3] = 'unknown'; 1104 | ErrorType[ErrorType['unsupportedFeature'] = 4] = 'unsupportedFeature'; 1105 | ErrorType[ErrorType['webRequestFailure'] = 5] = 'webRequestFailure'; 1106 | ErrorType[ErrorType['internalError'] = 6] = 'internalError'; 1107 | ErrorType[ErrorType['optionsError'] = 7] = 'optionsError'; 1108 | ErrorType[ErrorType['typeError'] = 8] = 'typeError'; 1109 | ErrorType[ErrorType['popupClosed'] = 9] = 'popupClosed'; 1110 | }(ErrorType || (ErrorType = {}))); 1111 | Object.defineProperty(exports, '__esModule', { value: true }); 1112 | exports.default = ErrorType; 1113 | }(require, exports)); 1114 | },{}],14:[function(require,module,exports){ 1115 | (function (require, exports, CallbackInvoker_1, Constants_1, DomainHint_1, ErrorHandler_1, ErrorType_1, Logging_1, OneDriveSdkError_1, StringUtilities_1, TypeValidators_1, UrlUtilities_1) { 1116 | 'use strict'; 1117 | var AAD_APPID_PATTERN = new RegExp('^[a-fA-F\\d]{8}-([a-fA-F\\d]{4}-){3}[a-fA-F\\d]{12}$'); 1118 | var InvokerOptions = function () { 1119 | function InvokerOptions(options) { 1120 | this.navEnabled = true; 1121 | this.needSharePointPermission = true; 1122 | this.clientId = TypeValidators_1.validateType(options.clientId, Constants_1.default.TYPE_STRING); 1123 | var cancelCallback = TypeValidators_1.validateCallback(options.cancel, true); 1124 | this.cancel = function () { 1125 | Logging_1.default.logMessage('user cancelled operation'); 1126 | if (cancelCallback) { 1127 | CallbackInvoker_1.invokeAppCallback(cancelCallback, true); 1128 | } 1129 | }; 1130 | var errorCallback = TypeValidators_1.validateCallback(options.error, true); 1131 | this.error = function (error) { 1132 | if (errorCallback) { 1133 | CallbackInvoker_1.invokeAppCallback(errorCallback, true, error); 1134 | } else { 1135 | throw error; 1136 | } 1137 | }; 1138 | this.parseAdvancedOptions(options); 1139 | this.redirectUri = this.redirectUri || UrlUtilities_1.trimUrlQuery(window.location.href); 1140 | this.endpointHint = this.endpointHint || DomainHint_1.default.aad; 1141 | InvokerOptions.checkClientId(this.clientId); 1142 | } 1143 | InvokerOptions.checkClientId = function (clientId) { 1144 | if (clientId) { 1145 | if (AAD_APPID_PATTERN.test(clientId)) { 1146 | Logging_1.default.logMessage('parsed client id: ' + clientId); 1147 | } else { 1148 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.unknown, StringUtilities_1.format('invalid format for client id \'{0}\' - AAD: 32 characters (HEX) GUID', clientId))); 1149 | } 1150 | } else { 1151 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.unknown, 'client id is missing in options')); 1152 | } 1153 | }; 1154 | InvokerOptions.prototype.needOauth = function () { 1155 | return this.needAPICall() && !this.accessToken || this.endpointHint === DomainHint_1.default.aad; 1156 | }; 1157 | InvokerOptions.prototype.parseAdvancedOptions = function (options) { 1158 | if (options.advanced) { 1159 | if (!!options.advanced.redirectUri) { 1160 | UrlUtilities_1.validateRedirectUrlHost(options.advanced.redirectUri); 1161 | this.redirectUri = options.advanced.redirectUri; 1162 | } 1163 | if (!!options.advanced.queryParameters) { 1164 | var itemQueries = UrlUtilities_1.readUrlParameters('?' + options.advanced.queryParameters); 1165 | for (var key in itemQueries) { 1166 | if (key.toLowerCase() !== 'select' && key.toLowerCase() !== 'expand') { 1167 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.optionsError, StringUtilities_1.format('unexpected query key: {0} is found in advanced.queryParameters', key))); 1168 | } 1169 | } 1170 | var selectQuery = itemQueries['select']; 1171 | var expandQuery = itemQueries['expand']; 1172 | if (selectQuery && expandQuery) { 1173 | this.queryParameters = StringUtilities_1.format('expand={0}&select={1}', expandQuery, selectQuery); 1174 | } else if (expandQuery) { 1175 | this.queryParameters = StringUtilities_1.format('expand={0}', expandQuery); 1176 | } else if (selectQuery) { 1177 | if ('select=' + selectQuery.split(',').sort().join(',') !== Constants_1.default.DEFAULT_QUERY_ITEM_PARAMETER) { 1178 | this.queryParameters = StringUtilities_1.format('select={0}', selectQuery); 1179 | } 1180 | } 1181 | } 1182 | if (!!options.advanced.endpointHint) { 1183 | if (options.advanced.endpointHint.toLowerCase() === Constants_1.default.VROOM_ENDPOINT_HINT) { 1184 | this.endpointHint = DomainHint_1.default.msa; 1185 | } else { 1186 | var domainHint = TypeValidators_1.validateType(options.advanced.endpointHint, 'string', false); 1187 | UrlUtilities_1.validateUrlProtocol(domainHint); 1188 | this.endpointHint = DomainHint_1.default.tenant; 1189 | this.siteUrl = domainHint; 1190 | } 1191 | if (!!options.advanced.accessToken) { 1192 | this.accessToken = options.advanced.accessToken; 1193 | } 1194 | } 1195 | if (!!options.advanced.iframeParentDiv) { 1196 | if (!options.advanced.iframeParentDiv.nodeName || options.advanced.iframeParentDiv.nodeName.toLowerCase() !== 'div') { 1197 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.optionsError, 'the iframe\'s parent div element is not a DOM object')).exposeToPublic(); 1198 | } 1199 | this.parentDiv = options.advanced.iframeParentDiv; 1200 | } 1201 | if (!!options.advanced.scopes) { 1202 | if (typeof options.advanced.scopes === 'string') { 1203 | this.scopes = [options.advanced.scopes]; 1204 | } else if (options.advanced.scopes instanceof Array) { 1205 | this.scopes = options.advanced.scopes; 1206 | } 1207 | } 1208 | this.linkType = options.advanced.linkType; 1209 | this.parseNavigationOptions(options.advanced.navigation); 1210 | this.loginHint = options.advanced.loginHint; 1211 | this.filter = options.advanced.filter; 1212 | } 1213 | }; 1214 | InvokerOptions.prototype.parseNavigationOptions = function (navigation) { 1215 | if (navigation) { 1216 | var entryLocation = navigation.entryLocation; 1217 | if (entryLocation) { 1218 | var _a = entryLocation.sharePoint, sitePath = _a.sitePath, listPath = _a.listPath; 1219 | if (sitePath) { 1220 | UrlUtilities_1.validateUrlProtocol(sitePath, ['HTTPS']); 1221 | } 1222 | if (listPath) { 1223 | UrlUtilities_1.validateUrlProtocol(listPath, ['HTTPS']); 1224 | } 1225 | this.navEntryLocation = entryLocation; 1226 | } 1227 | var sourceTypes = navigation.sourceTypes instanceof Array ? navigation.sourceTypes : navigation.sourceTypes ? [navigation.sourceTypes] : null; 1228 | if (!!sourceTypes) { 1229 | this.needSharePointPermission = !(sourceTypes.length === 1 && sourceTypes[0].toLowerCase() === 'onedrive'); 1230 | this.navSourceTypes = sourceTypes; 1231 | } 1232 | this.navEnabled = !navigation.disable; 1233 | } 1234 | }; 1235 | return InvokerOptions; 1236 | }(); 1237 | Object.defineProperty(exports, '__esModule', { value: true }); 1238 | exports.default = InvokerOptions; 1239 | }(require, exports, require('../utilities/CallbackInvoker'), require('../Constants'), require('./DomainHint'), require('../utilities/ErrorHandler'), require('./ErrorType'), require('../utilities/Logging'), require('./OneDriveSdkError'), require('../utilities/StringUtilities'), require('../utilities/TypeValidators'), require('../utilities/UrlUtilities'))); 1240 | },{"../Constants":1,"../utilities/CallbackInvoker":23,"../utilities/ErrorHandler":26,"../utilities/Logging":27,"../utilities/StringUtilities":30,"../utilities/TypeValidators":31,"../utilities/UrlUtilities":32,"./DomainHint":12,"./ErrorType":13,"./OneDriveSdkError":16}],15:[function(require,module,exports){ 1241 | (function (require, exports) { 1242 | 'use strict'; 1243 | var OauthEndpoint; 1244 | (function (OauthEndpoint) { 1245 | OauthEndpoint[OauthEndpoint['AAD'] = 0] = 'AAD'; 1246 | OauthEndpoint[OauthEndpoint['AADv2'] = 1] = 'AADv2'; 1247 | OauthEndpoint[OauthEndpoint['MSA'] = 2] = 'MSA'; 1248 | }(OauthEndpoint || (OauthEndpoint = {}))); 1249 | Object.defineProperty(exports, '__esModule', { value: true }); 1250 | exports.default = OauthEndpoint; 1251 | }(require, exports)); 1252 | },{}],16:[function(require,module,exports){ 1253 | (function (require, exports, ErrorType_1, StringUtilities_1) { 1254 | 'use strict'; 1255 | var OneDriveSdkError = function (_super) { 1256 | __extends(OneDriveSdkError, _super); 1257 | function OneDriveSdkError(errorCode, message) { 1258 | _super.call(this, message); 1259 | this.errorCode = ErrorType_1.default[errorCode]; 1260 | this.message = message; 1261 | } 1262 | OneDriveSdkError.prototype.toString = function () { 1263 | return StringUtilities_1.format('[OneDriveSDK Error] errorType: {0}, message: {1}', this.errorCode, this.message); 1264 | }; 1265 | return OneDriveSdkError; 1266 | }(Error); 1267 | Object.defineProperty(exports, '__esModule', { value: true }); 1268 | exports.default = OneDriveSdkError; 1269 | }(require, exports, require('../models/ErrorType'), require('../utilities/StringUtilities'))); 1270 | },{"../models/ErrorType":13,"../utilities/StringUtilities":30}],17:[function(require,module,exports){ 1271 | (function (require, exports) { 1272 | 'use strict'; 1273 | var PickerActionType; 1274 | (function (PickerActionType) { 1275 | PickerActionType[PickerActionType['download'] = 0] = 'download'; 1276 | PickerActionType[PickerActionType['query'] = 1] = 'query'; 1277 | PickerActionType[PickerActionType['share'] = 2] = 'share'; 1278 | }(PickerActionType || (PickerActionType = {}))); 1279 | Object.defineProperty(exports, '__esModule', { value: true }); 1280 | exports.default = PickerActionType; 1281 | }(require, exports)); 1282 | },{}],18:[function(require,module,exports){ 1283 | (function (require, exports, CallbackInvoker_1, Constants_1, InvokerOptions_1, Logging_1, PickerActionType_1, TypeValidators_1) { 1284 | 'use strict'; 1285 | var PickerOptions = function (_super) { 1286 | __extends(PickerOptions, _super); 1287 | function PickerOptions(options) { 1288 | _super.call(this, options); 1289 | var successCallback = TypeValidators_1.validateCallback(options.success, false); 1290 | this.success = function (files) { 1291 | Logging_1.default.logMessage('picker operation succeeded'); 1292 | CallbackInvoker_1.invokeAppCallback(successCallback, true, files); 1293 | }; 1294 | this.multiSelect = TypeValidators_1.validateType(options.multiSelect, Constants_1.default.TYPE_BOOLEAN, true, false); 1295 | var actionName = TypeValidators_1.validateType(options.action, Constants_1.default.TYPE_STRING, true, PickerActionType_1.default[PickerActionType_1.default.query]); 1296 | this.action = PickerActionType_1.default[actionName]; 1297 | if (options.advanced) { 1298 | this.createLinkParameters = options.advanced.createLinkParameters; 1299 | } 1300 | if (!this.scopes) { 1301 | this.scopes = [this.action === PickerActionType_1.default.share ? 'Files.ReadWrite' : 'Files.Read']; 1302 | } 1303 | } 1304 | PickerOptions.prototype.needAPICall = function () { 1305 | return !!this.queryParameters || this.action !== PickerActionType_1.default.query; 1306 | }; 1307 | return PickerOptions; 1308 | }(InvokerOptions_1.default); 1309 | Object.defineProperty(exports, '__esModule', { value: true }); 1310 | exports.default = PickerOptions; 1311 | }(require, exports, require('../utilities/CallbackInvoker'), require('../Constants'), require('./InvokerOptions'), require('../utilities/Logging'), require('./PickerActionType'), require('../utilities/TypeValidators'))); 1312 | },{"../Constants":1,"../utilities/CallbackInvoker":23,"../utilities/Logging":27,"../utilities/TypeValidators":31,"./InvokerOptions":14,"./PickerActionType":17}],19:[function(require,module,exports){ 1313 | (function (require, exports) { 1314 | 'use strict'; 1315 | var SaverActionType; 1316 | (function (SaverActionType) { 1317 | SaverActionType[SaverActionType['save'] = 0] = 'save'; 1318 | SaverActionType[SaverActionType['query'] = 1] = 'query'; 1319 | }(SaverActionType || (SaverActionType = {}))); 1320 | Object.defineProperty(exports, '__esModule', { value: true }); 1321 | exports.default = SaverActionType; 1322 | }(require, exports)); 1323 | },{}],20:[function(require,module,exports){ 1324 | (function (require, exports, CallbackInvoker_1, Constants_1, DomUtilities_1, ErrorHandler_1, ErrorType_1, InvokerOptions_1, Logging_1, OneDriveSdkError_1, SaverActionType_1, StringUtilities_1, TypeValidators_1, UploadType_1, UrlUtilities_1) { 1325 | 'use strict'; 1326 | var SaverOptions = function (_super) { 1327 | __extends(SaverOptions, _super); 1328 | function SaverOptions(options) { 1329 | _super.call(this, options); 1330 | var successCallback = TypeValidators_1.validateCallback(options.success, false); 1331 | this.success = function (folder) { 1332 | Logging_1.default.logMessage('saver operation succeeded'); 1333 | CallbackInvoker_1.invokeAppCallback(successCallback, true, folder); 1334 | }; 1335 | var progressCallback = TypeValidators_1.validateCallback(options.progress, true); 1336 | this.progress = function (percentage) { 1337 | Logging_1.default.logMessage(StringUtilities_1.format('upload progress: {0}%', percentage)); 1338 | if (progressCallback) { 1339 | CallbackInvoker_1.invokeAppCallback(progressCallback, false, percentage); 1340 | } 1341 | }; 1342 | var actionName = TypeValidators_1.validateType(options.action, Constants_1.default.TYPE_STRING, true, SaverActionType_1.default[SaverActionType_1.default.query]); 1343 | this.action = SaverActionType_1.default[actionName]; 1344 | if (this.action === SaverActionType_1.default.save) { 1345 | this._setFileInfo(options); 1346 | } 1347 | this.nameConflictBehavior = TypeValidators_1.validateType(options.nameConflictBehavior, Constants_1.default.TYPE_STRING, true, 'rename'); 1348 | if (!this.scopes) { 1349 | this.scopes = ['Files.ReadWrite']; 1350 | } 1351 | } 1352 | SaverOptions.prototype.needAPICall = function () { 1353 | return !!this.queryParameters || this.action === SaverActionType_1.default.save; 1354 | }; 1355 | SaverOptions.prototype._setFileInfo = function (options) { 1356 | if (options.sourceInputElementId && options.sourceUri) { 1357 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.optionsError, 'sourceUri and sourceInputElementId' + ' are provided, only one is required.')); 1358 | } 1359 | this.sourceInputElementId = options.sourceInputElementId; 1360 | this.sourceUri = options.sourceUri; 1361 | var fileName = TypeValidators_1.validateType(options.fileName, Constants_1.default.TYPE_STRING, true, null); 1362 | if (this.sourceUri) { 1363 | if (UrlUtilities_1.isPathFullUrl(this.sourceUri)) { 1364 | this.uploadType = UploadType_1.default.url; 1365 | this.fileName = fileName || UrlUtilities_1.getFileNameFromUrl(this.sourceUri); 1366 | if (!this.fileName) { 1367 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.optionsError, 'must supply a file name or a URL that ends with a file name')); 1368 | } 1369 | } else if (UrlUtilities_1.isPathDataUrl(this.sourceUri)) { 1370 | this.uploadType = UploadType_1.default.dataUrl; 1371 | this.fileName = fileName; 1372 | if (!this.fileName) { 1373 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.optionsError, 'must supply a file name for data URL uploads')); 1374 | } 1375 | } 1376 | } else if (this.sourceInputElementId) { 1377 | this.uploadType = UploadType_1.default.form; 1378 | this.fileInput = DomUtilities_1.getFileInput(this.sourceInputElementId); 1379 | this.fileName = fileName || this.fileInput.name; 1380 | } else { 1381 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.optionsError, 'please specified one type of resource to save')); 1382 | } 1383 | }; 1384 | return SaverOptions; 1385 | }(InvokerOptions_1.default); 1386 | Object.defineProperty(exports, '__esModule', { value: true }); 1387 | exports.default = SaverOptions; 1388 | }(require, exports, require('../utilities/CallbackInvoker'), require('../Constants'), require('../utilities/DomUtilities'), require('../utilities/ErrorHandler'), require('./ErrorType'), require('./InvokerOptions'), require('../utilities/Logging'), require('./OneDriveSdkError'), require('./SaverActionType'), require('../utilities/StringUtilities'), require('../utilities/TypeValidators'), require('./UploadType'), require('../utilities/UrlUtilities'))); 1389 | },{"../Constants":1,"../utilities/CallbackInvoker":23,"../utilities/DomUtilities":25,"../utilities/ErrorHandler":26,"../utilities/Logging":27,"../utilities/StringUtilities":30,"../utilities/TypeValidators":31,"../utilities/UrlUtilities":32,"./ErrorType":13,"./InvokerOptions":14,"./OneDriveSdkError":16,"./SaverActionType":19,"./UploadType":21}],21:[function(require,module,exports){ 1390 | (function (require, exports) { 1391 | 'use strict'; 1392 | var UploadType; 1393 | (function (UploadType) { 1394 | UploadType[UploadType['dataUrl'] = 0] = 'dataUrl'; 1395 | UploadType[UploadType['form'] = 1] = 'form'; 1396 | UploadType[UploadType['url'] = 2] = 'url'; 1397 | }(UploadType || (UploadType = {}))); 1398 | Object.defineProperty(exports, '__esModule', { value: true }); 1399 | exports.default = UploadType; 1400 | }(require, exports)); 1401 | },{}],22:[function(require,module,exports){ 1402 | (function (require, exports, ErrorType_1, ErrorHandler_1, OneDriveSdkError_1) { 1403 | 'use strict'; 1404 | var CACHE_NAME = 'odpickerv7cache'; 1405 | function getCacheItem(key) { 1406 | var cache = getCache(); 1407 | return cache[key]; 1408 | } 1409 | exports.getCacheItem = getCacheItem; 1410 | function setCacheItem(key, object) { 1411 | var cache = getCache(); 1412 | cache[key] = object; 1413 | setCache(cache); 1414 | } 1415 | exports.setCacheItem = setCacheItem; 1416 | function removeCacheItem(key) { 1417 | var cache = getCache(); 1418 | var deletedItem = cache[key]; 1419 | delete cache[key]; 1420 | setCache(cache); 1421 | return deletedItem; 1422 | } 1423 | exports.removeCacheItem = removeCacheItem; 1424 | function getCache() { 1425 | if (Storage) { 1426 | var cacheString = localStorage.getItem(CACHE_NAME); 1427 | var cache = JSON.parse(cacheString || '{}'); 1428 | return cache; 1429 | } else { 1430 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.unsupportedFeature, 'cache based on Storage is not supported in this browser')); 1431 | } 1432 | } 1433 | function setCache(cache) { 1434 | if (Storage) { 1435 | localStorage.setItem(CACHE_NAME, JSON.stringify(cache)); 1436 | } else { 1437 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.unsupportedFeature, 'cache based on Storage is not supported in this browser')); 1438 | } 1439 | } 1440 | }(require, exports, require('../models/ErrorType'), require('./ErrorHandler'), require('../models/OneDriveSdkError'))); 1441 | },{"../models/ErrorType":13,"../models/OneDriveSdkError":16,"./ErrorHandler":26}],23:[function(require,module,exports){ 1442 | (function (require, exports, Constants_1) { 1443 | 'use strict'; 1444 | function invokeAppCallback(callback, isFinalCallback) { 1445 | var args = []; 1446 | for (var _i = 2; _i < arguments.length; _i++) { 1447 | args[_i - 2] = arguments[_i]; 1448 | } 1449 | if (typeof callback === Constants_1.default.TYPE_FUNCTION) { 1450 | callback.apply(null, args); 1451 | } 1452 | } 1453 | exports.invokeAppCallback = invokeAppCallback; 1454 | function invokeCallbackAsynchronous(callback) { 1455 | var args = []; 1456 | for (var _i = 1; _i < arguments.length; _i++) { 1457 | args[_i - 1] = arguments[_i]; 1458 | } 1459 | window.setTimeout(function () { 1460 | callback.apply(null, args); 1461 | }, 0); 1462 | } 1463 | exports.invokeCallbackAsynchronous = invokeCallbackAsynchronous; 1464 | }(require, exports, require('../Constants'))); 1465 | },{"../Constants":1}],24:[function(require,module,exports){ 1466 | (function (require, exports) { 1467 | 'use strict'; 1468 | var Channel = function () { 1469 | function Channel(receiver) { 1470 | this.receiver = receiver; 1471 | } 1472 | Channel.prototype.send = function (data, origin) { 1473 | if (this.receiver) { 1474 | this.receiver.postMessage(data, origin); 1475 | } 1476 | }; 1477 | Channel.prototype.getReceiver = function () { 1478 | return this.receiver; 1479 | }; 1480 | return Channel; 1481 | }(); 1482 | Object.defineProperty(exports, '__esModule', { value: true }); 1483 | exports.default = Channel; 1484 | }(require, exports)); 1485 | },{}],25:[function(require,module,exports){ 1486 | (function (require, exports, ErrorHandler_1, ErrorType_1, OneDriveSdkError_1, UrlUtilities_1) { 1487 | 'use strict'; 1488 | var FORM_UPLOAD_SIZE_LIMIT = 104857600; 1489 | var FORM_UPLOAD_SIZE_LIMIT_STRING = '100 MB'; 1490 | var MESSAGE_LISTENERS = {}; 1491 | function getElementById(id) { 1492 | return document.getElementById(id); 1493 | } 1494 | exports.getElementById = getElementById; 1495 | function onDocumentReady(callback) { 1496 | if (document.readyState === 'interactive' || document.readyState === 'complete') { 1497 | callback(); 1498 | } else { 1499 | document.addEventListener('DOMContentLoaded', callback, false); 1500 | } 1501 | } 1502 | exports.onDocumentReady = onDocumentReady; 1503 | function onMessage(callback) { 1504 | var id = UrlUtilities_1.generateNonce() + '_' + new Date().getMilliseconds(); 1505 | window.addEventListener('message', callback); 1506 | MESSAGE_LISTENERS[id] = callback; 1507 | return id; 1508 | } 1509 | exports.onMessage = onMessage; 1510 | function removeMessageListener(id) { 1511 | var callback = MESSAGE_LISTENERS[id]; 1512 | if (callback) { 1513 | window.removeEventListener('message', callback); 1514 | } 1515 | } 1516 | exports.removeMessageListener = removeMessageListener; 1517 | function getFileInput(elementId) { 1518 | var fileInputElement = getElementById(elementId); 1519 | if (fileInputElement instanceof HTMLInputElement) { 1520 | if (fileInputElement.type !== 'file') { 1521 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.optionsError, 'input elemenet must be of type \'file\'')); 1522 | } 1523 | if (!fileInputElement.value) { 1524 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.optionsError, 'please a file to upload')); 1525 | return null; 1526 | } 1527 | var files = fileInputElement.files; 1528 | if (!files || !window['FileReader']) { 1529 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.unsupportedFeature, 'browser does not support Files API')); 1530 | } 1531 | if (files.length !== 1) { 1532 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.unsupportedFeature, 'can not upload more than one file at a time')); 1533 | } 1534 | var fileInput = files[0]; 1535 | if (!fileInput) { 1536 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.optionsError, 'missing file input')); 1537 | } 1538 | if (fileInput.size > FORM_UPLOAD_SIZE_LIMIT) { 1539 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.optionsError, 'the user has selected a file larger than ' + FORM_UPLOAD_SIZE_LIMIT_STRING)); 1540 | return null; 1541 | } 1542 | return fileInput; 1543 | } else { 1544 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.unknown, 'element was not an instance of an HTMLInputElement')); 1545 | } 1546 | } 1547 | exports.getFileInput = getFileInput; 1548 | function displayOverlay() { 1549 | var overlay = document.createElement('div'); 1550 | var overlayStyle = [ 1551 | 'position: fixed', 1552 | 'width: 100%', 1553 | 'height: 100%', 1554 | 'top: 0px', 1555 | 'left: 0px', 1556 | 'background-color: white', 1557 | 'opacity: 1', 1558 | 'z-index: 10000', 1559 | 'min-width: 40px', 1560 | 'min-height: 40px' 1561 | ]; 1562 | overlay.id = 'od-overlay'; 1563 | overlay.style.cssText = overlayStyle.join(';'); 1564 | var spinner = document.createElement('img'); 1565 | var spinnerStyle = [ 1566 | 'position: absolute', 1567 | 'margin: auto', 1568 | 'top: 0', 1569 | 'left: 0', 1570 | 'right: 0', 1571 | 'bottom: 0' 1572 | ]; 1573 | spinner.id = 'od-spinner'; 1574 | spinner.src = 'https://p.sfx.ms/common/spinner_grey_40_transparent.gif'; 1575 | spinner.style.cssText = spinnerStyle.join(';'); 1576 | overlay.appendChild(spinner); 1577 | var hiddenStyle = document.createElement('style'); 1578 | hiddenStyle.type = 'text/css'; 1579 | hiddenStyle.innerHTML = 'body { visibility: hidden !important; }'; 1580 | document.head.appendChild(hiddenStyle); 1581 | onDocumentReady(function () { 1582 | var documentBody = document.body; 1583 | if (documentBody !== null) { 1584 | documentBody.insertBefore(overlay, documentBody.firstChild); 1585 | } else { 1586 | document.createElement('body').appendChild(overlay); 1587 | } 1588 | document.head.removeChild(hiddenStyle); 1589 | }); 1590 | } 1591 | exports.displayOverlay = displayOverlay; 1592 | }(require, exports, require('./ErrorHandler'), require('../models/ErrorType'), require('../models/OneDriveSdkError'), require('./UrlUtilities'))); 1593 | },{"../models/ErrorType":13,"../models/OneDriveSdkError":16,"./ErrorHandler":26,"./UrlUtilities":32}],26:[function(require,module,exports){ 1594 | (function (require, exports, ErrorType_1) { 1595 | 'use strict'; 1596 | var ERROR_HANDLERS = []; 1597 | function registerErrorObserver(callback) { 1598 | ERROR_HANDLERS.push(callback); 1599 | } 1600 | exports.registerErrorObserver = registerErrorObserver; 1601 | function throwError(sdkError) { 1602 | if (sdkError.errorCode !== ErrorType_1.default[ErrorType_1.default.unknown]) { 1603 | for (var _i = 0, ERROR_HANDLERS_1 = ERROR_HANDLERS; _i < ERROR_HANDLERS_1.length; _i++) { 1604 | var callback = ERROR_HANDLERS_1[_i]; 1605 | callback(sdkError); 1606 | } 1607 | return { 1608 | exposeToPublic: function () { 1609 | throw sdkError; 1610 | } 1611 | }; 1612 | } else { 1613 | throw sdkError; 1614 | } 1615 | } 1616 | exports.throwError = throwError; 1617 | }(require, exports, require('../models/ErrorType'))); 1618 | },{"../models/ErrorType":13}],27:[function(require,module,exports){ 1619 | (function (require, exports) { 1620 | 'use strict'; 1621 | var ENABLE_LOGGING = 'onedrive_enable_logging'; 1622 | var LOG_PREFIX = '[OneDriveSDK] '; 1623 | var Logging = function () { 1624 | function Logging() { 1625 | } 1626 | Logging.logError = function (message) { 1627 | var objects = []; 1628 | for (var _i = 1; _i < arguments.length; _i++) { 1629 | objects[_i - 1] = arguments[_i]; 1630 | } 1631 | Logging._log(message, true, objects); 1632 | }; 1633 | Logging.logMessage = function (message) { 1634 | Logging._log(message, false); 1635 | }; 1636 | Logging._log = function (message, isError) { 1637 | var objects = []; 1638 | for (var _i = 2; _i < arguments.length; _i++) { 1639 | objects[_i - 2] = arguments[_i]; 1640 | } 1641 | if (isError || Logging.loggingEnabled || window[ENABLE_LOGGING]) { 1642 | console.log(LOG_PREFIX + message, objects); 1643 | } 1644 | }; 1645 | Logging.loggingEnabled = false; 1646 | return Logging; 1647 | }(); 1648 | Object.defineProperty(exports, '__esModule', { value: true }); 1649 | exports.default = Logging; 1650 | }(require, exports)); 1651 | },{}],28:[function(require,module,exports){ 1652 | (function (require, exports, Constants_1, Logging_1) { 1653 | 'use strict'; 1654 | function shallowClone(object) { 1655 | if (typeof object !== Constants_1.default.TYPE_OBJECT || !object) { 1656 | return null; 1657 | } 1658 | var clonedObject = {}; 1659 | for (var key in object) { 1660 | if (object.hasOwnProperty(key)) { 1661 | clonedObject[key] = object[key]; 1662 | } 1663 | } 1664 | return clonedObject; 1665 | } 1666 | exports.shallowClone = shallowClone; 1667 | function deserializeJSON(text) { 1668 | var deserializedObject = null; 1669 | try { 1670 | deserializedObject = JSON.parse(text); 1671 | } catch (error) { 1672 | Logging_1.default.logError('deserialization error' + error); 1673 | } 1674 | if (typeof deserializedObject !== Constants_1.default.TYPE_OBJECT || deserializedObject === null) { 1675 | deserializedObject = {}; 1676 | } 1677 | return deserializedObject; 1678 | } 1679 | exports.deserializeJSON = deserializeJSON; 1680 | function serializeJSON(value) { 1681 | return JSON.stringify(value); 1682 | } 1683 | exports.serializeJSON = serializeJSON; 1684 | }(require, exports, require('../Constants'), require('./Logging'))); 1685 | },{"../Constants":1,"./Logging":27}],29:[function(require,module,exports){ 1686 | (function (require, exports, ErrorHandler_1, ErrorType_1, Logging_1, OneDriveSdkError_1, UrlUtilities_1) { 1687 | 'use strict'; 1688 | var POPUP_WIDTH = 1024; 1689 | var POPUP_HEIGHT = 650; 1690 | exports.POPUP_PINGER_INTERVAL = 500; 1691 | var Popup = function () { 1692 | function Popup() { 1693 | } 1694 | Popup.getCurrentPopup = function () { 1695 | return Popup._currentPopup || new Popup(); 1696 | }; 1697 | Popup.setCurrentPopup = function (popup) { 1698 | Popup._currentPopup = popup; 1699 | }; 1700 | Popup.createPopupFeatures = function () { 1701 | var left = window.screenX + Math.max(window.outerWidth - POPUP_WIDTH, 0) / 2; 1702 | var top = window.screenY + Math.max(window.outerHeight - POPUP_HEIGHT, 0) / 2; 1703 | var features = [ 1704 | 'width=' + POPUP_WIDTH, 1705 | 'height=' + POPUP_HEIGHT, 1706 | 'top=' + top, 1707 | 'left=' + left, 1708 | 'status=no', 1709 | 'resizable=yes', 1710 | 'toolbar=no', 1711 | 'menubar=no', 1712 | 'scrollbars=yes' 1713 | ]; 1714 | return features.join(','); 1715 | }; 1716 | Popup.prototype.close = function () { 1717 | if (Popup.getCurrentPopup().isPopupOpen()) { 1718 | Popup.getCurrentPopup()._popup.close(); 1719 | Popup.setCurrentPopup(null); 1720 | } 1721 | }; 1722 | Popup.prototype.openPopup = function (url) { 1723 | var _this = this; 1724 | UrlUtilities_1.validateUrlProtocol(url); 1725 | if (Popup.getCurrentPopup().isPopupOpen()) { 1726 | Logging_1.default.logMessage('leaving current url: ' + this._url); 1727 | this._url = url; 1728 | Popup.getCurrentPopup().getPopupWindow().location.href = url; 1729 | } else { 1730 | this._url = url; 1731 | this._popup = window.open(url, '_blank', Popup.createPopupFeatures()); 1732 | if (!this._popup) { 1733 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.popupOpen, 'popup window is disconnected')).exposeToPublic(); 1734 | } else { 1735 | this._popup.focus(); 1736 | } 1737 | Popup.setCurrentPopup(this); 1738 | } 1739 | return new Promise(function (resolve, reject) { 1740 | var interval = setInterval(function () { 1741 | if (!_this.isPopupOpen()) { 1742 | window.clearInterval(interval); 1743 | resolve(); 1744 | } 1745 | }, exports.POPUP_PINGER_INTERVAL); 1746 | }); 1747 | }; 1748 | Popup.prototype.getPopupWindow = function () { 1749 | return this._popup; 1750 | }; 1751 | Popup.prototype.getCurrentUrl = function () { 1752 | return this._url; 1753 | }; 1754 | Popup.prototype.isPopupOpen = function () { 1755 | return !!this._popup && !this._popup.closed; 1756 | }; 1757 | return Popup; 1758 | }(); 1759 | Object.defineProperty(exports, '__esModule', { value: true }); 1760 | exports.default = Popup; 1761 | }(require, exports, require('./ErrorHandler'), require('../models/ErrorType'), require('./Logging'), require('../models/OneDriveSdkError'), require('../utilities/UrlUtilities'))); 1762 | },{"../models/ErrorType":13,"../models/OneDriveSdkError":16,"../utilities/UrlUtilities":32,"./ErrorHandler":26,"./Logging":27}],30:[function(require,module,exports){ 1763 | (function (require, exports) { 1764 | 'use strict'; 1765 | var FORMAT_ARGS_REGEX = /[\{\}]/g; 1766 | var FORMAT_REGEX = /\{\d+\}/g; 1767 | function format(str) { 1768 | var values = []; 1769 | for (var _i = 1; _i < arguments.length; _i++) { 1770 | values[_i - 1] = arguments[_i]; 1771 | } 1772 | var replacer = function (match) { 1773 | var replacement = values[match.replace(FORMAT_ARGS_REGEX, '')]; 1774 | if (replacement === null) { 1775 | replacement = ''; 1776 | } 1777 | return replacement; 1778 | }; 1779 | return str.replace(FORMAT_REGEX, replacer); 1780 | } 1781 | exports.format = format; 1782 | }(require, exports)); 1783 | },{}],31:[function(require,module,exports){ 1784 | (function (require, exports, Constants_1, ErrorHandler_1, ErrorType_1, Logging_1, ObjectUtilities_1, OneDriveSdkError_1, StringUtilities_1) { 1785 | 'use strict'; 1786 | function validateType(object, expectedType, optional, defaultValue, validValues) { 1787 | if (optional === void 0) { 1788 | optional = false; 1789 | } 1790 | if (object === undefined) { 1791 | if (optional) { 1792 | if (defaultValue !== undefined) { 1793 | Logging_1.default.logMessage('applying default value: ' + defaultValue); 1794 | return defaultValue; 1795 | } 1796 | } else { 1797 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.typeError, 'object was missing and not optional')); 1798 | } 1799 | return null; 1800 | } 1801 | var objectType = typeof object; 1802 | if (objectType !== expectedType) { 1803 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.typeError, StringUtilities_1.format('expected object type: \'{0}\', actual object type: \'{1}\'', expectedType, objectType))); 1804 | return null; 1805 | } 1806 | if (!isValidValue(object, validValues)) { 1807 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.typeError, StringUtilities_1.format('object does not match any valid values {0}', ObjectUtilities_1.serializeJSON(validValues)))); 1808 | return null; 1809 | } 1810 | return object; 1811 | } 1812 | exports.validateType = validateType; 1813 | function validateCallback(functionOption, optional) { 1814 | if (optional === void 0) { 1815 | optional = false; 1816 | } 1817 | if (functionOption === undefined) { 1818 | if (!optional) { 1819 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.typeError, 'function was missing and not optional')); 1820 | } 1821 | return null; 1822 | } 1823 | var functionType = typeof functionOption; 1824 | if (functionType !== Constants_1.default.TYPE_FUNCTION) { 1825 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.typeError, StringUtilities_1.format('expected function type: function | string, actual type: {0}', functionType))); 1826 | } 1827 | return functionOption; 1828 | } 1829 | exports.validateCallback = validateCallback; 1830 | function isValidValue(object, validValues) { 1831 | if (!Array.isArray(validValues)) { 1832 | return true; 1833 | } 1834 | for (var index in validValues) { 1835 | if (object === validValues[index]) { 1836 | return true; 1837 | } 1838 | } 1839 | return false; 1840 | } 1841 | }(require, exports, require('../Constants'), require('./ErrorHandler'), require('../models/ErrorType'), require('./Logging'), require('./ObjectUtilities'), require('../models/OneDriveSdkError'), require('./StringUtilities'))); 1842 | },{"../Constants":1,"../models/ErrorType":13,"../models/OneDriveSdkError":16,"./ErrorHandler":26,"./Logging":27,"./ObjectUtilities":28,"./StringUtilities":30}],32:[function(require,module,exports){ 1843 | (function (require, exports, Constants_1, ErrorHandler_1, ErrorType_1, OneDriveSdkError_1, StringUtilities_1) { 1844 | 'use strict'; 1845 | var PROTOCOL_HTTP = 'HTTP'; 1846 | var PROTOCOL_HTTPS = 'HTTPS'; 1847 | function appendToPath(baseUrl, path) { 1848 | return baseUrl + (baseUrl.charAt(baseUrl.length - 1) !== '/' ? '/' : '') + path; 1849 | } 1850 | exports.appendToPath = appendToPath; 1851 | function appendQueryString(baseUrl, queryKey, queryValue) { 1852 | return appendQueryStrings(baseUrl, (_a = {}, _a[queryKey] = queryValue, _a)); 1853 | var _a; 1854 | } 1855 | exports.appendQueryString = appendQueryString; 1856 | function appendQueryStrings(baseUrl, queryParameters, isAspx) { 1857 | if (!queryParameters || Object.keys(queryParameters).length === 0) { 1858 | return baseUrl; 1859 | } 1860 | if (isAspx) { 1861 | baseUrl += '#'; 1862 | } else if (baseUrl.indexOf('?') === -1) { 1863 | baseUrl += '?'; 1864 | } else if (baseUrl.charAt(baseUrl.length - 1) !== '&') { 1865 | baseUrl += '&'; 1866 | } 1867 | var queryString = ''; 1868 | for (var key in queryParameters) { 1869 | queryString += (queryString.length ? '&' : '') + StringUtilities_1.format('{0}={1}', encodeURIComponent(key), encodeURIComponent(queryParameters[key])); 1870 | } 1871 | return baseUrl + queryString; 1872 | } 1873 | exports.appendQueryStrings = appendQueryStrings; 1874 | function readCurrentUrlParameters() { 1875 | return readUrlParameters(window.location.href); 1876 | } 1877 | exports.readCurrentUrlParameters = readCurrentUrlParameters; 1878 | function readUrlParameters(url) { 1879 | var queryParamters = {}; 1880 | var queryStart = url.indexOf('?') + 1; 1881 | var hashStart = url.indexOf('#') + 1; 1882 | if (queryStart > 0) { 1883 | var queryEnd = hashStart > queryStart ? hashStart - 1 : url.length; 1884 | deserializeParameters(url.substring(queryStart, queryEnd), queryParamters); 1885 | } 1886 | if (hashStart > 0) { 1887 | deserializeParameters(url.substring(hashStart), queryParamters); 1888 | } 1889 | return queryParamters; 1890 | } 1891 | exports.readUrlParameters = readUrlParameters; 1892 | function redirect(url) { 1893 | validateUrlProtocol(url); 1894 | window.location.replace(url); 1895 | } 1896 | exports.redirect = redirect; 1897 | function trimUrlQuery(url) { 1898 | var separators = [ 1899 | '?', 1900 | '#' 1901 | ]; 1902 | for (var index in separators) { 1903 | var charIndex = url.indexOf(separators[index]); 1904 | if (charIndex > 0) { 1905 | url = url.substring(0, charIndex); 1906 | } 1907 | } 1908 | return url; 1909 | } 1910 | exports.trimUrlQuery = trimUrlQuery; 1911 | function getFileNameFromUrl(url) { 1912 | var trimmedUrl = trimUrlQuery(url); 1913 | return trimmedUrl.substr(trimmedUrl.lastIndexOf('/') + 1); 1914 | } 1915 | exports.getFileNameFromUrl = getFileNameFromUrl; 1916 | function getOrigin(url) { 1917 | return appendToPath(url.replace(/^((\w+:)?\/\/[^\/]+\/?).*$/, '$1'), ''); 1918 | } 1919 | exports.getOrigin = getOrigin; 1920 | function isPathFullUrl(path) { 1921 | return path.indexOf('https://') === 0 || path.indexOf('http://') === 0; 1922 | } 1923 | exports.isPathFullUrl = isPathFullUrl; 1924 | function isPathDataUrl(path) { 1925 | return path.indexOf('data:') === 0; 1926 | } 1927 | exports.isPathDataUrl = isPathDataUrl; 1928 | function generateNonce() { 1929 | var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; 1930 | var text = ''; 1931 | for (var i = 0; i < Constants_1.default.NONCE_LENGTH; i++) { 1932 | text += possible.charAt(Math.floor(Math.random() * possible.length)); 1933 | } 1934 | return text; 1935 | } 1936 | exports.generateNonce = generateNonce; 1937 | function validateUrlProtocol(url, protocols) { 1938 | protocols = protocols ? protocols : [ 1939 | PROTOCOL_HTTP, 1940 | PROTOCOL_HTTPS 1941 | ]; 1942 | for (var _i = 0, protocols_1 = protocols; _i < protocols_1.length; _i++) { 1943 | var protocol = protocols_1[_i]; 1944 | if (url.toUpperCase().indexOf(protocol) === 0) { 1945 | return; 1946 | } 1947 | } 1948 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.optionsError, StringUtilities_1.format('uri {0} does not match protocol(s): ' + protocols, url))).exposeToPublic(); 1949 | } 1950 | exports.validateUrlProtocol = validateUrlProtocol; 1951 | function validateRedirectUrlHost(url) { 1952 | validateUrlProtocol(url); 1953 | if (url.indexOf('://') > -1) { 1954 | var domain = url.split('/')[2]; 1955 | if (domain !== window.location.host) { 1956 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.optionsError, 'redirect uri is not in the same domain as picker sdk')).exposeToPublic(); 1957 | } 1958 | } else { 1959 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.optionsError, 'redirect uri is not an absolute url')).exposeToPublic(); 1960 | } 1961 | } 1962 | exports.validateRedirectUrlHost = validateRedirectUrlHost; 1963 | function deserializeParameters(query, queryParameters) { 1964 | var properties = query.split('&'); 1965 | for (var i = 0; i < properties.length; i++) { 1966 | var property = properties[i].split('='); 1967 | if (property.length === 2) { 1968 | queryParameters[decodeURIComponent(property[0])] = decodeURIComponent(property[1]); 1969 | } 1970 | } 1971 | } 1972 | }(require, exports, require('../Constants'), require('./ErrorHandler'), require('../models/ErrorType'), require('../models/OneDriveSdkError'), require('./StringUtilities'))); 1973 | },{"../Constants":1,"../models/ErrorType":13,"../models/OneDriveSdkError":16,"./ErrorHandler":26,"./StringUtilities":30}],33:[function(require,module,exports){ 1974 | (function (require, exports, ApiEndpoint_1, Constants_1, ErrorHandler_1, ErrorType_1, Logging_1, OneDriveSdkError_1, StringUtilities_1) { 1975 | 'use strict'; 1976 | var REQUEST_TIMEOUT = 30000; 1977 | var EXCEPTION_STATUS = -1; 1978 | var TIMEOUT_STATUS = -2; 1979 | var ABORT_STATUS = -3; 1980 | var LEGACY_MSA_APPID_PATTERN = new RegExp('^([a-fA-F0-9]){16}$'); 1981 | var XHR = function () { 1982 | function XHR(options) { 1983 | this._url = options.url; 1984 | this._json = options.json; 1985 | this._headers = options.headers || {}; 1986 | this._method = options.method; 1987 | this._clientId = options.clientId; 1988 | this._apiEndpoint = options.apiEndpoint || ApiEndpoint_1.default.msa; 1989 | ErrorHandler_1.registerErrorObserver(this._abortRequest); 1990 | } 1991 | XHR.statusCodeToString = function (statusCode) { 1992 | switch (statusCode) { 1993 | case -1: 1994 | return 'EXCEPTION'; 1995 | case -2: 1996 | return 'TIMEOUT'; 1997 | case -3: 1998 | return 'REQUEST ABORTED'; 1999 | default: 2000 | return statusCode.toString(); 2001 | } 2002 | }; 2003 | XHR.prototype.start = function (successCallback, failureCallback) { 2004 | var _this = this; 2005 | try { 2006 | this._successCallback = successCallback; 2007 | this._failureCallback = failureCallback; 2008 | this._request = new XMLHttpRequest(); 2009 | this._request.ontimeout = this._onTimeout; 2010 | this._request.onload = function () { 2011 | var status = _this._request.status; 2012 | if (status < 400 && status > 0) { 2013 | _this._callSuccessCallback(status); 2014 | } else { 2015 | _this._callFailureCallback(status); 2016 | } 2017 | }; 2018 | if (!this._method) { 2019 | this._method = this._json ? XHR.HTTP_POST : XHR.HTTP_GET; 2020 | } 2021 | this._request.open(this._method, this._url, true); 2022 | this._request.timeout = REQUEST_TIMEOUT; 2023 | this._setHeaders(); 2024 | Logging_1.default.logMessage('starting request to: ' + this._url); 2025 | this._request.send(this._json); 2026 | } catch (error) { 2027 | this._callFailureCallback(EXCEPTION_STATUS, error); 2028 | } 2029 | }; 2030 | XHR.prototype.upload = function (data, successCallback, failureCallback, progressCallback) { 2031 | var _this = this; 2032 | try { 2033 | this._successCallback = successCallback; 2034 | this._progressCallback = progressCallback; 2035 | this._failureCallback = failureCallback; 2036 | this._request = new XMLHttpRequest(); 2037 | this._request.ontimeout = this._onTimeout; 2038 | this._method = XHR.HTTP_PUT; 2039 | this._request.open(this._method, this._url, true); 2040 | this._setHeaders(); 2041 | this._request.onload = function (event) { 2042 | _this._completed = true; 2043 | var status = _this._request.status; 2044 | if (status === 200 || status === 201 || status === 202) { 2045 | _this._callSuccessCallback(status); 2046 | } else { 2047 | _this._callFailureCallback(status, event); 2048 | } 2049 | }; 2050 | this._request.onerror = function (event) { 2051 | _this._completed = true; 2052 | _this._callFailureCallback(_this._request.status, event); 2053 | }; 2054 | this._request.upload.onprogress = function (event) { 2055 | if (event.lengthComputable) { 2056 | var uploadProgress = { 2057 | bytesTransferred: event.loaded, 2058 | totalBytes: event.total, 2059 | progressPercentage: event.total === 0 ? 0 : event.loaded / event.total * 100 2060 | }; 2061 | _this._callProgressCallback(uploadProgress); 2062 | } 2063 | }; 2064 | Logging_1.default.logMessage('starting upload to: ' + this._url); 2065 | this._request.send(data); 2066 | } catch (error) { 2067 | this._callFailureCallback(EXCEPTION_STATUS, error); 2068 | } 2069 | }; 2070 | XHR.prototype._callSuccessCallback = function (status) { 2071 | Logging_1.default.logMessage('calling xhr success callback, status: ' + XHR.statusCodeToString(status)); 2072 | this._successCallback(this._request, status, this._url); 2073 | }; 2074 | XHR.prototype._callFailureCallback = function (status, error) { 2075 | Logging_1.default.logError('calling xhr failure callback, status: ' + XHR.statusCodeToString(status), this._request, error); 2076 | this._failureCallback(this._request, status, status === TIMEOUT_STATUS); 2077 | }; 2078 | XHR.prototype._callProgressCallback = function (uploadProgress) { 2079 | Logging_1.default.logMessage('calling xhr upload progress callback'); 2080 | this._progressCallback(this._request, uploadProgress); 2081 | }; 2082 | XHR.prototype._abortRequest = function () { 2083 | if (this && !this._completed) { 2084 | this._completed = true; 2085 | if (this._request) { 2086 | try { 2087 | this._request.abort(); 2088 | } catch (error) { 2089 | } 2090 | } 2091 | this._callFailureCallback(ABORT_STATUS); 2092 | } 2093 | }; 2094 | XHR.prototype._onTimeout = function () { 2095 | if (!this._completed) { 2096 | this._completed = true; 2097 | this._callFailureCallback(TIMEOUT_STATUS); 2098 | } 2099 | }; 2100 | XHR.prototype._setHeaders = function () { 2101 | for (var x in this._headers) { 2102 | this._request.setRequestHeader(x, this._headers[x]); 2103 | } 2104 | if (this._clientId) { 2105 | var idToRecord = this._clientId; 2106 | if (LEGACY_MSA_APPID_PATTERN.test(this._clientId)) { 2107 | idToRecord = '0x' + this._clientId; 2108 | } 2109 | this._request.setRequestHeader('Application', '0x' + idToRecord); 2110 | } 2111 | var sdkVersion = StringUtilities_1.format('{0}={1}', 'SDK-Version', Constants_1.default.SDK_VERSION); 2112 | switch (this._apiEndpoint) { 2113 | case ApiEndpoint_1.default.graph_odb: 2114 | case ApiEndpoint_1.default.filesV2: 2115 | this._request.setRequestHeader('X-ClientService-ClientTag', sdkVersion); 2116 | break; 2117 | case ApiEndpoint_1.default.graph_odc: 2118 | case ApiEndpoint_1.default.msa: 2119 | this._request.setRequestHeader('X-RequestStats', sdkVersion); 2120 | break; 2121 | default: 2122 | ErrorHandler_1.throwError(new OneDriveSdkError_1.default(ErrorType_1.default.internalError, 'invalid API endpoint: ' + this._apiEndpoint)); 2123 | } 2124 | if (this._method === XHR.HTTP_POST) { 2125 | this._request.setRequestHeader('Content-Type', this._json ? 'application/json' : 'text/plain'); 2126 | } 2127 | }; 2128 | XHR.HTTP_GET = 'GET'; 2129 | XHR.HTTP_POST = 'POST'; 2130 | XHR.HTTP_PUT = 'PUT'; 2131 | return XHR; 2132 | }(); 2133 | Object.defineProperty(exports, '__esModule', { value: true }); 2134 | exports.default = XHR; 2135 | }(require, exports, require('../models/ApiEndpoint'), require('../Constants'), require('./ErrorHandler'), require('../models/ErrorType'), require('./Logging'), require('../models/OneDriveSdkError'), require('./StringUtilities'))); 2136 | },{"../Constants":1,"../models/ApiEndpoint":11,"../models/ErrorType":13,"../models/OneDriveSdkError":16,"./ErrorHandler":26,"./Logging":27,"./StringUtilities":30}],34:[function(require,module,exports){ 2137 | /*! 2138 | * @overview es6-promise - a tiny implementation of Promises/A+. 2139 | * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald) 2140 | * @license Licensed under MIT license 2141 | * See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE 2142 | * @version 3.3.1 2143 | */ 2144 | 2145 | (function (global, factory) { 2146 | typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 2147 | typeof define === 'function' && define.amd ? define(factory) : 2148 | (global.ES6Promise = factory()); 2149 | }(this, (function () { 'use strict'; 2150 | 2151 | function objectOrFunction(x) { 2152 | return typeof x === 'function' || typeof x === 'object' && x !== null; 2153 | } 2154 | 2155 | function isFunction(x) { 2156 | return typeof x === 'function'; 2157 | } 2158 | 2159 | var _isArray = undefined; 2160 | if (!Array.isArray) { 2161 | _isArray = function (x) { 2162 | return Object.prototype.toString.call(x) === '[object Array]'; 2163 | }; 2164 | } else { 2165 | _isArray = Array.isArray; 2166 | } 2167 | 2168 | var isArray = _isArray; 2169 | 2170 | var len = 0; 2171 | var vertxNext = undefined; 2172 | var customSchedulerFn = undefined; 2173 | 2174 | var asap = function asap(callback, arg) { 2175 | queue[len] = callback; 2176 | queue[len + 1] = arg; 2177 | len += 2; 2178 | if (len === 2) { 2179 | // If len is 2, that means that we need to schedule an async flush. 2180 | // If additional callbacks are queued before the queue is flushed, they 2181 | // will be processed by this flush that we are scheduling. 2182 | if (customSchedulerFn) { 2183 | customSchedulerFn(flush); 2184 | } else { 2185 | scheduleFlush(); 2186 | } 2187 | } 2188 | }; 2189 | 2190 | function setScheduler(scheduleFn) { 2191 | customSchedulerFn = scheduleFn; 2192 | } 2193 | 2194 | function setAsap(asapFn) { 2195 | asap = asapFn; 2196 | } 2197 | 2198 | var browserWindow = typeof window !== 'undefined' ? window : undefined; 2199 | var browserGlobal = browserWindow || {}; 2200 | var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver; 2201 | var isNode = typeof self === 'undefined' && typeof process !== 'undefined' && ({}).toString.call(process) === '[object process]'; 2202 | 2203 | // test for web worker but not in IE10 2204 | var isWorker = typeof Uint8ClampedArray !== 'undefined' && typeof importScripts !== 'undefined' && typeof MessageChannel !== 'undefined'; 2205 | 2206 | // node 2207 | function useNextTick() { 2208 | // node version 0.10.x displays a deprecation warning when nextTick is used recursively 2209 | // see https://github.com/cujojs/when/issues/410 for details 2210 | return function () { 2211 | return process.nextTick(flush); 2212 | }; 2213 | } 2214 | 2215 | // vertx 2216 | function useVertxTimer() { 2217 | return function () { 2218 | vertxNext(flush); 2219 | }; 2220 | } 2221 | 2222 | function useMutationObserver() { 2223 | var iterations = 0; 2224 | var observer = new BrowserMutationObserver(flush); 2225 | var node = document.createTextNode(''); 2226 | observer.observe(node, { characterData: true }); 2227 | 2228 | return function () { 2229 | node.data = iterations = ++iterations % 2; 2230 | }; 2231 | } 2232 | 2233 | // web worker 2234 | function useMessageChannel() { 2235 | var channel = new MessageChannel(); 2236 | channel.port1.onmessage = flush; 2237 | return function () { 2238 | return channel.port2.postMessage(0); 2239 | }; 2240 | } 2241 | 2242 | function useSetTimeout() { 2243 | // Store setTimeout reference so es6-promise will be unaffected by 2244 | // other code modifying setTimeout (like sinon.useFakeTimers()) 2245 | var globalSetTimeout = setTimeout; 2246 | return function () { 2247 | return globalSetTimeout(flush, 1); 2248 | }; 2249 | } 2250 | 2251 | var queue = new Array(1000); 2252 | function flush() { 2253 | for (var i = 0; i < len; i += 2) { 2254 | var callback = queue[i]; 2255 | var arg = queue[i + 1]; 2256 | 2257 | callback(arg); 2258 | 2259 | queue[i] = undefined; 2260 | queue[i + 1] = undefined; 2261 | } 2262 | 2263 | len = 0; 2264 | } 2265 | 2266 | function attemptVertx() { 2267 | try { 2268 | var r = require; 2269 | var vertx = r('vertx'); 2270 | vertxNext = vertx.runOnLoop || vertx.runOnContext; 2271 | return useVertxTimer(); 2272 | } catch (e) { 2273 | return useSetTimeout(); 2274 | } 2275 | } 2276 | 2277 | var scheduleFlush = undefined; 2278 | // Decide what async method to use to triggering processing of queued callbacks: 2279 | if (isNode) { 2280 | scheduleFlush = useNextTick(); 2281 | } else if (BrowserMutationObserver) { 2282 | scheduleFlush = useMutationObserver(); 2283 | } else if (isWorker) { 2284 | scheduleFlush = useMessageChannel(); 2285 | } else if (browserWindow === undefined && typeof require === 'function') { 2286 | scheduleFlush = attemptVertx(); 2287 | } else { 2288 | scheduleFlush = useSetTimeout(); 2289 | } 2290 | 2291 | function then(onFulfillment, onRejection) { 2292 | var _arguments = arguments; 2293 | 2294 | var parent = this; 2295 | 2296 | var child = new this.constructor(noop); 2297 | 2298 | if (child[PROMISE_ID] === undefined) { 2299 | makePromise(child); 2300 | } 2301 | 2302 | var _state = parent._state; 2303 | 2304 | if (_state) { 2305 | (function () { 2306 | var callback = _arguments[_state - 1]; 2307 | asap(function () { 2308 | return invokeCallback(_state, child, callback, parent._result); 2309 | }); 2310 | })(); 2311 | } else { 2312 | subscribe(parent, child, onFulfillment, onRejection); 2313 | } 2314 | 2315 | return child; 2316 | } 2317 | 2318 | /** 2319 | `Promise.resolve` returns a promise that will become resolved with the 2320 | passed `value`. It is shorthand for the following: 2321 | 2322 | ```javascript 2323 | let promise = new Promise(function(resolve, reject){ 2324 | resolve(1); 2325 | }); 2326 | 2327 | promise.then(function(value){ 2328 | // value === 1 2329 | }); 2330 | ``` 2331 | 2332 | Instead of writing the above, your code now simply becomes the following: 2333 | 2334 | ```javascript 2335 | let promise = Promise.resolve(1); 2336 | 2337 | promise.then(function(value){ 2338 | // value === 1 2339 | }); 2340 | ``` 2341 | 2342 | @method resolve 2343 | @static 2344 | @param {Any} value value that the returned promise will be resolved with 2345 | Useful for tooling. 2346 | @return {Promise} a promise that will become fulfilled with the given 2347 | `value` 2348 | */ 2349 | function resolve(object) { 2350 | /*jshint validthis:true */ 2351 | var Constructor = this; 2352 | 2353 | if (object && typeof object === 'object' && object.constructor === Constructor) { 2354 | return object; 2355 | } 2356 | 2357 | var promise = new Constructor(noop); 2358 | _resolve(promise, object); 2359 | return promise; 2360 | } 2361 | 2362 | var PROMISE_ID = Math.random().toString(36).substring(16); 2363 | 2364 | function noop() {} 2365 | 2366 | var PENDING = void 0; 2367 | var FULFILLED = 1; 2368 | var REJECTED = 2; 2369 | 2370 | var GET_THEN_ERROR = new ErrorObject(); 2371 | 2372 | function selfFulfillment() { 2373 | return new TypeError("You cannot resolve a promise with itself"); 2374 | } 2375 | 2376 | function cannotReturnOwn() { 2377 | return new TypeError('A promises callback cannot return that same promise.'); 2378 | } 2379 | 2380 | function getThen(promise) { 2381 | try { 2382 | return promise.then; 2383 | } catch (error) { 2384 | GET_THEN_ERROR.error = error; 2385 | return GET_THEN_ERROR; 2386 | } 2387 | } 2388 | 2389 | function tryThen(then, value, fulfillmentHandler, rejectionHandler) { 2390 | try { 2391 | then.call(value, fulfillmentHandler, rejectionHandler); 2392 | } catch (e) { 2393 | return e; 2394 | } 2395 | } 2396 | 2397 | function handleForeignThenable(promise, thenable, then) { 2398 | asap(function (promise) { 2399 | var sealed = false; 2400 | var error = tryThen(then, thenable, function (value) { 2401 | if (sealed) { 2402 | return; 2403 | } 2404 | sealed = true; 2405 | if (thenable !== value) { 2406 | _resolve(promise, value); 2407 | } else { 2408 | fulfill(promise, value); 2409 | } 2410 | }, function (reason) { 2411 | if (sealed) { 2412 | return; 2413 | } 2414 | sealed = true; 2415 | 2416 | _reject(promise, reason); 2417 | }, 'Settle: ' + (promise._label || ' unknown promise')); 2418 | 2419 | if (!sealed && error) { 2420 | sealed = true; 2421 | _reject(promise, error); 2422 | } 2423 | }, promise); 2424 | } 2425 | 2426 | function handleOwnThenable(promise, thenable) { 2427 | if (thenable._state === FULFILLED) { 2428 | fulfill(promise, thenable._result); 2429 | } else if (thenable._state === REJECTED) { 2430 | _reject(promise, thenable._result); 2431 | } else { 2432 | subscribe(thenable, undefined, function (value) { 2433 | return _resolve(promise, value); 2434 | }, function (reason) { 2435 | return _reject(promise, reason); 2436 | }); 2437 | } 2438 | } 2439 | 2440 | function handleMaybeThenable(promise, maybeThenable, then$$) { 2441 | if (maybeThenable.constructor === promise.constructor && then$$ === then && maybeThenable.constructor.resolve === resolve) { 2442 | handleOwnThenable(promise, maybeThenable); 2443 | } else { 2444 | if (then$$ === GET_THEN_ERROR) { 2445 | _reject(promise, GET_THEN_ERROR.error); 2446 | } else if (then$$ === undefined) { 2447 | fulfill(promise, maybeThenable); 2448 | } else if (isFunction(then$$)) { 2449 | handleForeignThenable(promise, maybeThenable, then$$); 2450 | } else { 2451 | fulfill(promise, maybeThenable); 2452 | } 2453 | } 2454 | } 2455 | 2456 | function _resolve(promise, value) { 2457 | if (promise === value) { 2458 | _reject(promise, selfFulfillment()); 2459 | } else if (objectOrFunction(value)) { 2460 | handleMaybeThenable(promise, value, getThen(value)); 2461 | } else { 2462 | fulfill(promise, value); 2463 | } 2464 | } 2465 | 2466 | function publishRejection(promise) { 2467 | if (promise._onerror) { 2468 | promise._onerror(promise._result); 2469 | } 2470 | 2471 | publish(promise); 2472 | } 2473 | 2474 | function fulfill(promise, value) { 2475 | if (promise._state !== PENDING) { 2476 | return; 2477 | } 2478 | 2479 | promise._result = value; 2480 | promise._state = FULFILLED; 2481 | 2482 | if (promise._subscribers.length !== 0) { 2483 | asap(publish, promise); 2484 | } 2485 | } 2486 | 2487 | function _reject(promise, reason) { 2488 | if (promise._state !== PENDING) { 2489 | return; 2490 | } 2491 | promise._state = REJECTED; 2492 | promise._result = reason; 2493 | 2494 | asap(publishRejection, promise); 2495 | } 2496 | 2497 | function subscribe(parent, child, onFulfillment, onRejection) { 2498 | var _subscribers = parent._subscribers; 2499 | var length = _subscribers.length; 2500 | 2501 | parent._onerror = null; 2502 | 2503 | _subscribers[length] = child; 2504 | _subscribers[length + FULFILLED] = onFulfillment; 2505 | _subscribers[length + REJECTED] = onRejection; 2506 | 2507 | if (length === 0 && parent._state) { 2508 | asap(publish, parent); 2509 | } 2510 | } 2511 | 2512 | function publish(promise) { 2513 | var subscribers = promise._subscribers; 2514 | var settled = promise._state; 2515 | 2516 | if (subscribers.length === 0) { 2517 | return; 2518 | } 2519 | 2520 | var child = undefined, 2521 | callback = undefined, 2522 | detail = promise._result; 2523 | 2524 | for (var i = 0; i < subscribers.length; i += 3) { 2525 | child = subscribers[i]; 2526 | callback = subscribers[i + settled]; 2527 | 2528 | if (child) { 2529 | invokeCallback(settled, child, callback, detail); 2530 | } else { 2531 | callback(detail); 2532 | } 2533 | } 2534 | 2535 | promise._subscribers.length = 0; 2536 | } 2537 | 2538 | function ErrorObject() { 2539 | this.error = null; 2540 | } 2541 | 2542 | var TRY_CATCH_ERROR = new ErrorObject(); 2543 | 2544 | function tryCatch(callback, detail) { 2545 | try { 2546 | return callback(detail); 2547 | } catch (e) { 2548 | TRY_CATCH_ERROR.error = e; 2549 | return TRY_CATCH_ERROR; 2550 | } 2551 | } 2552 | 2553 | function invokeCallback(settled, promise, callback, detail) { 2554 | var hasCallback = isFunction(callback), 2555 | value = undefined, 2556 | error = undefined, 2557 | succeeded = undefined, 2558 | failed = undefined; 2559 | 2560 | if (hasCallback) { 2561 | value = tryCatch(callback, detail); 2562 | 2563 | if (value === TRY_CATCH_ERROR) { 2564 | failed = true; 2565 | error = value.error; 2566 | value = null; 2567 | } else { 2568 | succeeded = true; 2569 | } 2570 | 2571 | if (promise === value) { 2572 | _reject(promise, cannotReturnOwn()); 2573 | return; 2574 | } 2575 | } else { 2576 | value = detail; 2577 | succeeded = true; 2578 | } 2579 | 2580 | if (promise._state !== PENDING) { 2581 | // noop 2582 | } else if (hasCallback && succeeded) { 2583 | _resolve(promise, value); 2584 | } else if (failed) { 2585 | _reject(promise, error); 2586 | } else if (settled === FULFILLED) { 2587 | fulfill(promise, value); 2588 | } else if (settled === REJECTED) { 2589 | _reject(promise, value); 2590 | } 2591 | } 2592 | 2593 | function initializePromise(promise, resolver) { 2594 | try { 2595 | resolver(function resolvePromise(value) { 2596 | _resolve(promise, value); 2597 | }, function rejectPromise(reason) { 2598 | _reject(promise, reason); 2599 | }); 2600 | } catch (e) { 2601 | _reject(promise, e); 2602 | } 2603 | } 2604 | 2605 | var id = 0; 2606 | function nextId() { 2607 | return id++; 2608 | } 2609 | 2610 | function makePromise(promise) { 2611 | promise[PROMISE_ID] = id++; 2612 | promise._state = undefined; 2613 | promise._result = undefined; 2614 | promise._subscribers = []; 2615 | } 2616 | 2617 | function Enumerator(Constructor, input) { 2618 | this._instanceConstructor = Constructor; 2619 | this.promise = new Constructor(noop); 2620 | 2621 | if (!this.promise[PROMISE_ID]) { 2622 | makePromise(this.promise); 2623 | } 2624 | 2625 | if (isArray(input)) { 2626 | this._input = input; 2627 | this.length = input.length; 2628 | this._remaining = input.length; 2629 | 2630 | this._result = new Array(this.length); 2631 | 2632 | if (this.length === 0) { 2633 | fulfill(this.promise, this._result); 2634 | } else { 2635 | this.length = this.length || 0; 2636 | this._enumerate(); 2637 | if (this._remaining === 0) { 2638 | fulfill(this.promise, this._result); 2639 | } 2640 | } 2641 | } else { 2642 | _reject(this.promise, validationError()); 2643 | } 2644 | } 2645 | 2646 | function validationError() { 2647 | return new Error('Array Methods must be provided an Array'); 2648 | }; 2649 | 2650 | Enumerator.prototype._enumerate = function () { 2651 | var length = this.length; 2652 | var _input = this._input; 2653 | 2654 | for (var i = 0; this._state === PENDING && i < length; i++) { 2655 | this._eachEntry(_input[i], i); 2656 | } 2657 | }; 2658 | 2659 | Enumerator.prototype._eachEntry = function (entry, i) { 2660 | var c = this._instanceConstructor; 2661 | var resolve$$ = c.resolve; 2662 | 2663 | if (resolve$$ === resolve) { 2664 | var _then = getThen(entry); 2665 | 2666 | if (_then === then && entry._state !== PENDING) { 2667 | this._settledAt(entry._state, i, entry._result); 2668 | } else if (typeof _then !== 'function') { 2669 | this._remaining--; 2670 | this._result[i] = entry; 2671 | } else if (c === Promise) { 2672 | var promise = new c(noop); 2673 | handleMaybeThenable(promise, entry, _then); 2674 | this._willSettleAt(promise, i); 2675 | } else { 2676 | this._willSettleAt(new c(function (resolve$$) { 2677 | return resolve$$(entry); 2678 | }), i); 2679 | } 2680 | } else { 2681 | this._willSettleAt(resolve$$(entry), i); 2682 | } 2683 | }; 2684 | 2685 | Enumerator.prototype._settledAt = function (state, i, value) { 2686 | var promise = this.promise; 2687 | 2688 | if (promise._state === PENDING) { 2689 | this._remaining--; 2690 | 2691 | if (state === REJECTED) { 2692 | _reject(promise, value); 2693 | } else { 2694 | this._result[i] = value; 2695 | } 2696 | } 2697 | 2698 | if (this._remaining === 0) { 2699 | fulfill(promise, this._result); 2700 | } 2701 | }; 2702 | 2703 | Enumerator.prototype._willSettleAt = function (promise, i) { 2704 | var enumerator = this; 2705 | 2706 | subscribe(promise, undefined, function (value) { 2707 | return enumerator._settledAt(FULFILLED, i, value); 2708 | }, function (reason) { 2709 | return enumerator._settledAt(REJECTED, i, reason); 2710 | }); 2711 | }; 2712 | 2713 | /** 2714 | `Promise.all` accepts an array of promises, and returns a new promise which 2715 | is fulfilled with an array of fulfillment values for the passed promises, or 2716 | rejected with the reason of the first passed promise to be rejected. It casts all 2717 | elements of the passed iterable to promises as it runs this algorithm. 2718 | 2719 | Example: 2720 | 2721 | ```javascript 2722 | let promise1 = resolve(1); 2723 | let promise2 = resolve(2); 2724 | let promise3 = resolve(3); 2725 | let promises = [ promise1, promise2, promise3 ]; 2726 | 2727 | Promise.all(promises).then(function(array){ 2728 | // The array here would be [ 1, 2, 3 ]; 2729 | }); 2730 | ``` 2731 | 2732 | If any of the `promises` given to `all` are rejected, the first promise 2733 | that is rejected will be given as an argument to the returned promises's 2734 | rejection handler. For example: 2735 | 2736 | Example: 2737 | 2738 | ```javascript 2739 | let promise1 = resolve(1); 2740 | let promise2 = reject(new Error("2")); 2741 | let promise3 = reject(new Error("3")); 2742 | let promises = [ promise1, promise2, promise3 ]; 2743 | 2744 | Promise.all(promises).then(function(array){ 2745 | // Code here never runs because there are rejected promises! 2746 | }, function(error) { 2747 | // error.message === "2" 2748 | }); 2749 | ``` 2750 | 2751 | @method all 2752 | @static 2753 | @param {Array} entries array of promises 2754 | @param {String} label optional string for labeling the promise. 2755 | Useful for tooling. 2756 | @return {Promise} promise that is fulfilled when all `promises` have been 2757 | fulfilled, or rejected if any of them become rejected. 2758 | @static 2759 | */ 2760 | function all(entries) { 2761 | return new Enumerator(this, entries).promise; 2762 | } 2763 | 2764 | /** 2765 | `Promise.race` returns a new promise which is settled in the same way as the 2766 | first passed promise to settle. 2767 | 2768 | Example: 2769 | 2770 | ```javascript 2771 | let promise1 = new Promise(function(resolve, reject){ 2772 | setTimeout(function(){ 2773 | resolve('promise 1'); 2774 | }, 200); 2775 | }); 2776 | 2777 | let promise2 = new Promise(function(resolve, reject){ 2778 | setTimeout(function(){ 2779 | resolve('promise 2'); 2780 | }, 100); 2781 | }); 2782 | 2783 | Promise.race([promise1, promise2]).then(function(result){ 2784 | // result === 'promise 2' because it was resolved before promise1 2785 | // was resolved. 2786 | }); 2787 | ``` 2788 | 2789 | `Promise.race` is deterministic in that only the state of the first 2790 | settled promise matters. For example, even if other promises given to the 2791 | `promises` array argument are resolved, but the first settled promise has 2792 | become rejected before the other promises became fulfilled, the returned 2793 | promise will become rejected: 2794 | 2795 | ```javascript 2796 | let promise1 = new Promise(function(resolve, reject){ 2797 | setTimeout(function(){ 2798 | resolve('promise 1'); 2799 | }, 200); 2800 | }); 2801 | 2802 | let promise2 = new Promise(function(resolve, reject){ 2803 | setTimeout(function(){ 2804 | reject(new Error('promise 2')); 2805 | }, 100); 2806 | }); 2807 | 2808 | Promise.race([promise1, promise2]).then(function(result){ 2809 | // Code here never runs 2810 | }, function(reason){ 2811 | // reason.message === 'promise 2' because promise 2 became rejected before 2812 | // promise 1 became fulfilled 2813 | }); 2814 | ``` 2815 | 2816 | An example real-world use case is implementing timeouts: 2817 | 2818 | ```javascript 2819 | Promise.race([ajax('foo.json'), timeout(5000)]) 2820 | ``` 2821 | 2822 | @method race 2823 | @static 2824 | @param {Array} promises array of promises to observe 2825 | Useful for tooling. 2826 | @return {Promise} a promise which settles in the same way as the first passed 2827 | promise to settle. 2828 | */ 2829 | function race(entries) { 2830 | /*jshint validthis:true */ 2831 | var Constructor = this; 2832 | 2833 | if (!isArray(entries)) { 2834 | return new Constructor(function (_, reject) { 2835 | return reject(new TypeError('You must pass an array to race.')); 2836 | }); 2837 | } else { 2838 | return new Constructor(function (resolve, reject) { 2839 | var length = entries.length; 2840 | for (var i = 0; i < length; i++) { 2841 | Constructor.resolve(entries[i]).then(resolve, reject); 2842 | } 2843 | }); 2844 | } 2845 | } 2846 | 2847 | /** 2848 | `Promise.reject` returns a promise rejected with the passed `reason`. 2849 | It is shorthand for the following: 2850 | 2851 | ```javascript 2852 | let promise = new Promise(function(resolve, reject){ 2853 | reject(new Error('WHOOPS')); 2854 | }); 2855 | 2856 | promise.then(function(value){ 2857 | // Code here doesn't run because the promise is rejected! 2858 | }, function(reason){ 2859 | // reason.message === 'WHOOPS' 2860 | }); 2861 | ``` 2862 | 2863 | Instead of writing the above, your code now simply becomes the following: 2864 | 2865 | ```javascript 2866 | let promise = Promise.reject(new Error('WHOOPS')); 2867 | 2868 | promise.then(function(value){ 2869 | // Code here doesn't run because the promise is rejected! 2870 | }, function(reason){ 2871 | // reason.message === 'WHOOPS' 2872 | }); 2873 | ``` 2874 | 2875 | @method reject 2876 | @static 2877 | @param {Any} reason value that the returned promise will be rejected with. 2878 | Useful for tooling. 2879 | @return {Promise} a promise rejected with the given `reason`. 2880 | */ 2881 | function reject(reason) { 2882 | /*jshint validthis:true */ 2883 | var Constructor = this; 2884 | var promise = new Constructor(noop); 2885 | _reject(promise, reason); 2886 | return promise; 2887 | } 2888 | 2889 | function needsResolver() { 2890 | throw new TypeError('You must pass a resolver function as the first argument to the promise constructor'); 2891 | } 2892 | 2893 | function needsNew() { 2894 | throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function."); 2895 | } 2896 | 2897 | /** 2898 | Promise objects represent the eventual result of an asynchronous operation. The 2899 | primary way of interacting with a promise is through its `then` method, which 2900 | registers callbacks to receive either a promise's eventual value or the reason 2901 | why the promise cannot be fulfilled. 2902 | 2903 | Terminology 2904 | ----------- 2905 | 2906 | - `promise` is an object or function with a `then` method whose behavior conforms to this specification. 2907 | - `thenable` is an object or function that defines a `then` method. 2908 | - `value` is any legal JavaScript value (including undefined, a thenable, or a promise). 2909 | - `exception` is a value that is thrown using the throw statement. 2910 | - `reason` is a value that indicates why a promise was rejected. 2911 | - `settled` the final resting state of a promise, fulfilled or rejected. 2912 | 2913 | A promise can be in one of three states: pending, fulfilled, or rejected. 2914 | 2915 | Promises that are fulfilled have a fulfillment value and are in the fulfilled 2916 | state. Promises that are rejected have a rejection reason and are in the 2917 | rejected state. A fulfillment value is never a thenable. 2918 | 2919 | Promises can also be said to *resolve* a value. If this value is also a 2920 | promise, then the original promise's settled state will match the value's 2921 | settled state. So a promise that *resolves* a promise that rejects will 2922 | itself reject, and a promise that *resolves* a promise that fulfills will 2923 | itself fulfill. 2924 | 2925 | 2926 | Basic Usage: 2927 | ------------ 2928 | 2929 | ```js 2930 | let promise = new Promise(function(resolve, reject) { 2931 | // on success 2932 | resolve(value); 2933 | 2934 | // on failure 2935 | reject(reason); 2936 | }); 2937 | 2938 | promise.then(function(value) { 2939 | // on fulfillment 2940 | }, function(reason) { 2941 | // on rejection 2942 | }); 2943 | ``` 2944 | 2945 | Advanced Usage: 2946 | --------------- 2947 | 2948 | Promises shine when abstracting away asynchronous interactions such as 2949 | `XMLHttpRequest`s. 2950 | 2951 | ```js 2952 | function getJSON(url) { 2953 | return new Promise(function(resolve, reject){ 2954 | let xhr = new XMLHttpRequest(); 2955 | 2956 | xhr.open('GET', url); 2957 | xhr.onreadystatechange = handler; 2958 | xhr.responseType = 'json'; 2959 | xhr.setRequestHeader('Accept', 'application/json'); 2960 | xhr.send(); 2961 | 2962 | function handler() { 2963 | if (this.readyState === this.DONE) { 2964 | if (this.status === 200) { 2965 | resolve(this.response); 2966 | } else { 2967 | reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']')); 2968 | } 2969 | } 2970 | }; 2971 | }); 2972 | } 2973 | 2974 | getJSON('/posts.json').then(function(json) { 2975 | // on fulfillment 2976 | }, function(reason) { 2977 | // on rejection 2978 | }); 2979 | ``` 2980 | 2981 | Unlike callbacks, promises are great composable primitives. 2982 | 2983 | ```js 2984 | Promise.all([ 2985 | getJSON('/posts'), 2986 | getJSON('/comments') 2987 | ]).then(function(values){ 2988 | values[0] // => postsJSON 2989 | values[1] // => commentsJSON 2990 | 2991 | return values; 2992 | }); 2993 | ``` 2994 | 2995 | @class Promise 2996 | @param {function} resolver 2997 | Useful for tooling. 2998 | @constructor 2999 | */ 3000 | function Promise(resolver) { 3001 | this[PROMISE_ID] = nextId(); 3002 | this._result = this._state = undefined; 3003 | this._subscribers = []; 3004 | 3005 | if (noop !== resolver) { 3006 | typeof resolver !== 'function' && needsResolver(); 3007 | this instanceof Promise ? initializePromise(this, resolver) : needsNew(); 3008 | } 3009 | } 3010 | 3011 | Promise.all = all; 3012 | Promise.race = race; 3013 | Promise.resolve = resolve; 3014 | Promise.reject = reject; 3015 | Promise._setScheduler = setScheduler; 3016 | Promise._setAsap = setAsap; 3017 | Promise._asap = asap; 3018 | 3019 | Promise.prototype = { 3020 | constructor: Promise, 3021 | 3022 | /** 3023 | The primary way of interacting with a promise is through its `then` method, 3024 | which registers callbacks to receive either a promise's eventual value or the 3025 | reason why the promise cannot be fulfilled. 3026 | 3027 | ```js 3028 | findUser().then(function(user){ 3029 | // user is available 3030 | }, function(reason){ 3031 | // user is unavailable, and you are given the reason why 3032 | }); 3033 | ``` 3034 | 3035 | Chaining 3036 | -------- 3037 | 3038 | The return value of `then` is itself a promise. This second, 'downstream' 3039 | promise is resolved with the return value of the first promise's fulfillment 3040 | or rejection handler, or rejected if the handler throws an exception. 3041 | 3042 | ```js 3043 | findUser().then(function (user) { 3044 | return user.name; 3045 | }, function (reason) { 3046 | return 'default name'; 3047 | }).then(function (userName) { 3048 | // If `findUser` fulfilled, `userName` will be the user's name, otherwise it 3049 | // will be `'default name'` 3050 | }); 3051 | 3052 | findUser().then(function (user) { 3053 | throw new Error('Found user, but still unhappy'); 3054 | }, function (reason) { 3055 | throw new Error('`findUser` rejected and we're unhappy'); 3056 | }).then(function (value) { 3057 | // never reached 3058 | }, function (reason) { 3059 | // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'. 3060 | // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'. 3061 | }); 3062 | ``` 3063 | If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream. 3064 | 3065 | ```js 3066 | findUser().then(function (user) { 3067 | throw new PedagogicalException('Upstream error'); 3068 | }).then(function (value) { 3069 | // never reached 3070 | }).then(function (value) { 3071 | // never reached 3072 | }, function (reason) { 3073 | // The `PedgagocialException` is propagated all the way down to here 3074 | }); 3075 | ``` 3076 | 3077 | Assimilation 3078 | ------------ 3079 | 3080 | Sometimes the value you want to propagate to a downstream promise can only be 3081 | retrieved asynchronously. This can be achieved by returning a promise in the 3082 | fulfillment or rejection handler. The downstream promise will then be pending 3083 | until the returned promise is settled. This is called *assimilation*. 3084 | 3085 | ```js 3086 | findUser().then(function (user) { 3087 | return findCommentsByAuthor(user); 3088 | }).then(function (comments) { 3089 | // The user's comments are now available 3090 | }); 3091 | ``` 3092 | 3093 | If the assimliated promise rejects, then the downstream promise will also reject. 3094 | 3095 | ```js 3096 | findUser().then(function (user) { 3097 | return findCommentsByAuthor(user); 3098 | }).then(function (comments) { 3099 | // If `findCommentsByAuthor` fulfills, we'll have the value here 3100 | }, function (reason) { 3101 | // If `findCommentsByAuthor` rejects, we'll have the reason here 3102 | }); 3103 | ``` 3104 | 3105 | Simple Example 3106 | -------------- 3107 | 3108 | Synchronous Example 3109 | 3110 | ```javascript 3111 | let result; 3112 | 3113 | try { 3114 | result = findResult(); 3115 | // success 3116 | } catch(reason) { 3117 | // failure 3118 | } 3119 | ``` 3120 | 3121 | Errback Example 3122 | 3123 | ```js 3124 | findResult(function(result, err){ 3125 | if (err) { 3126 | // failure 3127 | } else { 3128 | // success 3129 | } 3130 | }); 3131 | ``` 3132 | 3133 | Promise Example; 3134 | 3135 | ```javascript 3136 | findResult().then(function(result){ 3137 | // success 3138 | }, function(reason){ 3139 | // failure 3140 | }); 3141 | ``` 3142 | 3143 | Advanced Example 3144 | -------------- 3145 | 3146 | Synchronous Example 3147 | 3148 | ```javascript 3149 | let author, books; 3150 | 3151 | try { 3152 | author = findAuthor(); 3153 | books = findBooksByAuthor(author); 3154 | // success 3155 | } catch(reason) { 3156 | // failure 3157 | } 3158 | ``` 3159 | 3160 | Errback Example 3161 | 3162 | ```js 3163 | 3164 | function foundBooks(books) { 3165 | 3166 | } 3167 | 3168 | function failure(reason) { 3169 | 3170 | } 3171 | 3172 | findAuthor(function(author, err){ 3173 | if (err) { 3174 | failure(err); 3175 | // failure 3176 | } else { 3177 | try { 3178 | findBoooksByAuthor(author, function(books, err) { 3179 | if (err) { 3180 | failure(err); 3181 | } else { 3182 | try { 3183 | foundBooks(books); 3184 | } catch(reason) { 3185 | failure(reason); 3186 | } 3187 | } 3188 | }); 3189 | } catch(error) { 3190 | failure(err); 3191 | } 3192 | // success 3193 | } 3194 | }); 3195 | ``` 3196 | 3197 | Promise Example; 3198 | 3199 | ```javascript 3200 | findAuthor(). 3201 | then(findBooksByAuthor). 3202 | then(function(books){ 3203 | // found books 3204 | }).catch(function(reason){ 3205 | // something went wrong 3206 | }); 3207 | ``` 3208 | 3209 | @method then 3210 | @param {Function} onFulfilled 3211 | @param {Function} onRejected 3212 | Useful for tooling. 3213 | @return {Promise} 3214 | */ 3215 | then: then, 3216 | 3217 | /** 3218 | `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same 3219 | as the catch block of a try/catch statement. 3220 | 3221 | ```js 3222 | function findAuthor(){ 3223 | throw new Error('couldn't find that author'); 3224 | } 3225 | 3226 | // synchronous 3227 | try { 3228 | findAuthor(); 3229 | } catch(reason) { 3230 | // something went wrong 3231 | } 3232 | 3233 | // async with promises 3234 | findAuthor().catch(function(reason){ 3235 | // something went wrong 3236 | }); 3237 | ``` 3238 | 3239 | @method catch 3240 | @param {Function} onRejection 3241 | Useful for tooling. 3242 | @return {Promise} 3243 | */ 3244 | 'catch': function _catch(onRejection) { 3245 | return this.then(null, onRejection); 3246 | } 3247 | }; 3248 | 3249 | function polyfill() { 3250 | var local = undefined; 3251 | 3252 | if (typeof global !== 'undefined') { 3253 | local = global; 3254 | } else if (typeof self !== 'undefined') { 3255 | local = self; 3256 | } else { 3257 | try { 3258 | local = Function('return this')(); 3259 | } catch (e) { 3260 | throw new Error('polyfill failed because global object is unavailable in this environment'); 3261 | } 3262 | } 3263 | 3264 | var P = local.Promise; 3265 | 3266 | if (P) { 3267 | var promiseToString = null; 3268 | try { 3269 | promiseToString = Object.prototype.toString.call(P.resolve()); 3270 | } catch (e) { 3271 | // silently ignored 3272 | } 3273 | 3274 | if (promiseToString === '[object Promise]' && !P.cast) { 3275 | return; 3276 | } 3277 | } 3278 | 3279 | local.Promise = Promise; 3280 | } 3281 | 3282 | polyfill(); 3283 | // Strange compat.. 3284 | Promise.polyfill = polyfill; 3285 | Promise.Promise = Promise; 3286 | 3287 | return Promise; 3288 | 3289 | }))); 3290 | 3291 | },{}]},{},[2])(2) 3292 | }); -------------------------------------------------------------------------------- /js/markdown-editor.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE in the project root for license information. 2 | 3 | var markdownEditor = { 4 | applicationId: "5fc58006-b25f-4eaf-8f30-527c6fa7e5f5", 5 | defaultFileName: "MD file.md", 6 | microsoftGraphApiRoot: "https://graph.microsoft.com/v1.0/", 7 | 8 | /************ Open *************/ 9 | 10 | // Open a new file by invoking the picker to select a file from OneDrive. 11 | openFile: function () { 12 | var editor = this; 13 | 14 | // Build the options that we pass to the picker 15 | var options = { 16 | // Specify the options for the picker (we want download links and only one file). 17 | clientId: editor.applicationId, 18 | action: "download", 19 | multiSelect: false, 20 | advanced: { 21 | /* Filter the files that are available for selection */ 22 | filter: ".md,.mdown,.txt", 23 | /* Request a few additional properties */ 24 | queryParameters: "select=*,name,size", 25 | /* Request a read-write scope for the access token */ 26 | scopes: ["Files.ReadWrite"] 27 | }, 28 | success: function (files) { 29 | // Update our state to remember how we can use the API to write back to this file. 30 | editor.accessToken = files.accessToken; 31 | 32 | // Get the first selected file (since we're not doing multi-select) and open it 33 | var selectedFile = files.value[0]; 34 | editor.openItemInEditor(selectedFile); 35 | }, 36 | error: function (e) { editor.showError("Error occurred while picking a file: " + e, e); }, 37 | }; 38 | OneDrive.open(options); 39 | }, 40 | 41 | // Method used to open the picked file into the editor. Resets local state and downloads the file from OneDrive. 42 | openItemInEditor: function (fileItem) { 43 | var editor = this; 44 | editor.lastSelectedFile = fileItem; 45 | // Retrieve the contents of the file and load it into our editor 46 | var downloadLink = fileItem["@microsoft.graph.downloadUrl"]; 47 | 48 | // Use JQuery AJAX to download the file 49 | $.ajax(downloadLink, { 50 | success: function (data, status, xhr) { 51 | 52 | // load the file into the editor 53 | editor.setEditorBody(xhr.responseText); 54 | editor.setFilename(fileItem.name); 55 | $("#canvas").attr("disabled", false); 56 | editor.openFileID = fileItem.id; 57 | }, 58 | error: function(xhr, status, err) { 59 | editor.showError(err); 60 | } 61 | }); 62 | }, 63 | 64 | /************ Save As *************/ 65 | 66 | // Save the contents of the editor back to the server using a new filename. Invokes 67 | // the picker to allow the user to select a folder where the file should be saved. 68 | saveAsFile: function () { 69 | var editor = this; 70 | var filename = ""; 71 | 72 | // Ensure we have a valid filename for the file 73 | if (editor.lastSelectedFile) { 74 | filename = editor.lastSelectedFile.name; 75 | } 76 | if (!filename || filename == "") { 77 | filename = editor.defaultFileName; 78 | } 79 | 80 | // Build the picker options to query for a folder where the file should be saved. 81 | var options = { 82 | clientId: editor.applicationId, 83 | action: "query", 84 | advanced: { 85 | // Request additional parameters when we save the file 86 | queryParameters: "select=id,name,parentReference" 87 | }, 88 | success: function (selection) { 89 | // The return here is the folder where we need to upload the item 90 | var folder = selection.value[0]; 91 | 92 | 93 | if (!editor.lastSelectedFile) { 94 | // Remember the details of the file we just created 95 | editor.lastSelectedFile = { 96 | id: null, 97 | name: filename, 98 | parentReference: { 99 | driveId: folder.parentReference.driveId, 100 | id: folder.id 101 | } 102 | } 103 | } else { 104 | // Update the lastSelectedFile item with the details of the new destination folder 105 | editor.lastSelectedFile.parentReference.driveId = folder.parentReference.driveId; 106 | editor.lastSelectedFile.parentReference.id = folder.id 107 | } 108 | 109 | // Store the access token from the file picker, so we don't need to get a new one 110 | editor.accessToken = selection.accessToken; 111 | 112 | // Call the saveFileWithToken method, which will write this file back with Microsoft Graph 113 | editor.saveFileWithAPI( { uploadIntoParentFolder: true }); 114 | }, 115 | error: function (e) { editor.showError("An error occurred while saving the file: " + e, e); } 116 | }; 117 | 118 | // Launch the picker 119 | OneDrive.save(options); 120 | }, 121 | 122 | /************ Save *************/ 123 | 124 | // Save the contents of the editor back to the file that was opened. If no file was 125 | // currently open, the saveAsFile method is invoked. 126 | saveFile: function () { 127 | var editor = this; 128 | // Check to see if we know about an open file. If not, revert to the save as flow. 129 | if (editor.openFileID == "") { 130 | editor.saveAsFile(); 131 | return; 132 | } 133 | 134 | // Since we're using the API to write back changes, make sure we have a valid 135 | // access_token and then invoke saveFileWithToken. 136 | editor.saveFileWithAPI(); 137 | }, 138 | 139 | // Save the contents of the editor back to a target drive item. Requires an access token 140 | // and a parent reference in the state object. 141 | saveFileWithAPI: function (state) { 142 | var editor = this; 143 | if (editor.accessToken == null) { 144 | // An error occurred and we don't have a token available to save. 145 | editor.showError("Unable to save file due to an authentication error. Try using Save As instead."); 146 | return; 147 | } 148 | 149 | // This method uses the REST API directly instead of the file picker, 150 | // using some values that we stored from the picker when we opened the item. 151 | var url = editor.generateGraphUrl(editor.lastSelectedFile, (state && state.uploadIntoParentFolder) ? true : false, "/content"); 152 | 153 | var bodyContent = $("#canvas").val().replace(/\r\n|\r|\n/g, "\r\n"); 154 | 155 | // Call the REST API to PUT the text value to the contents of the file. 156 | $.ajax(url, { 157 | method: "PUT", 158 | contentType: "application/octet-stream", 159 | data: bodyContent, 160 | processData: false, 161 | headers: { Authorization: "Bearer" + editor.accessToken }, 162 | success: function(data, status, xhr) { 163 | if (data && data.name && data.parentReference) { 164 | editor.lastSelectedFile = data; 165 | editor.showSuccessMessage("File was saved."); 166 | } 167 | }, 168 | error: function(xhr, status, err) { 169 | editor.showError(err); 170 | } 171 | }); 172 | }, 173 | 174 | 175 | /************ Rename File *************/ 176 | 177 | // Rename the currently open file by providing a new name for the file via an input 178 | // dialog 179 | renameFile: function () { 180 | var editor = this; 181 | 182 | var oldFilename = (editor.lastSelectedFile && editor.lastSelectedFile.name) ? editor.lastSelectedFile.name : editor.defaultFileName; 183 | var newFilename = window.prompt("Rename file", oldFilename); 184 | if (!newFilename) return; 185 | 186 | editor.setFilename(newFilename); 187 | 188 | if (editor.lastSelectedFile && editor.lastSelectedFile.id) { 189 | // Patch the file to rename it in real time. 190 | editor.lastSelectedFile.name = newFilename; 191 | editor.patchDriveItemWithAPI({ propertyList: [ "name" ]} ); 192 | } else { 193 | // The file hasn't been saved yet, so the rename is just local 194 | } 195 | }, 196 | 197 | // Patch a DriveItem via the Microsoft Graph. Expects an access token and the state 198 | // parameter to have a driveItem, propertyList, and parent (reference to this object) properties. 199 | // driveItem is the item to update, which needs to have its id and parentReference.driveId property set to the item to patch. 200 | // propertyList is an array of properties on the driveItem that will be submitted as the patch. These must be top-level properties of the driveItem 201 | patchDriveItemWithAPI: function(state) { 202 | var editor = this; 203 | if (editor.accessToken == null) { 204 | // An error occurred and we don't have a token available to save. 205 | editor.showError("Unable to save file due to an authentication error. Try using Save As instead."); 206 | return; 207 | } 208 | 209 | if (state == null) { 210 | editor.showError("The state parameter is required for this method."); 211 | return; 212 | } 213 | 214 | var item = editor.lastSelectedFile; 215 | var propList = state.propertyList; 216 | 217 | // For PATCH we don't invoke the picker, we're going to use the REST API directly 218 | var url = editor.generateGraphUrl(item, false, null); 219 | 220 | // Copy the values into patchData from the driveItem, based on names of properties in propertyList 221 | var patchData = { }; 222 | for(var i=0, len = propList.length; i < len; i++) 223 | { 224 | patchData[propList[i]] = item[propList[i]]; 225 | } 226 | 227 | $.ajax(url, { 228 | method: "PATCH", 229 | contentType: "application/json; charset=UTF-8", 230 | data: JSON.stringify(patchData), 231 | headers: { Authorization: "Bearer" + editor.accessToken }, 232 | success: function(data, status, xhr) { 233 | if (data && data.name && data.parentReference) { 234 | editor.showSuccessMessage("File was updated successfully."); 235 | editor.lastSelectedFile = data; 236 | } 237 | }, 238 | error: function(xhr, status, err) { 239 | editor.showError("Unable to patch file metadata: " + err); 240 | } 241 | }); 242 | }, 243 | 244 | /***************** Share File ***************/ 245 | shareFile: function () { 246 | var editor = this; 247 | // Make a request to Microsoft Graph to retrieve a default sharing URL for the file. 248 | if (!editor.lastSelectedFile || !editor.lastSelectedFile.id) 249 | { 250 | editor.showError("You need to save the file first before you can share it."); 251 | return; 252 | } 253 | 254 | editor.getSharingLinkWithAPI(); 255 | }, 256 | 257 | getSharingLinkWithAPI: function() { 258 | var editor = this; 259 | var driveItem = editor.lastSelectedFile; 260 | 261 | var url = editor.generateGraphUrl(driveItem, false, "/createLink"); 262 | var requestBody = { type: "view" }; 263 | 264 | $.ajax(url, { 265 | method: "POST", 266 | contentType: "application/json; charset=UTF-8", 267 | data: JSON.stringify(requestBody), 268 | headers: { Authorization: "Bearer" + editor.accessToken }, 269 | success: function(data, status, xhr) { 270 | if (data && data.link && data.link.webUrl) { 271 | window.prompt("View-only sharing link", data.link.webUrl); 272 | } else { 273 | editor.showError("Unable to retrieve a sharing link for this file."); 274 | } 275 | }, 276 | error: function(xhr, status, err) { 277 | editor.showError("Unable to retrieve a sharing link for this file."); 278 | } 279 | }); 280 | }, 281 | 282 | // Used to generate the Microsoft Graph URL for a target item, with a few parameters 283 | // uploadIntoParentFolder: bool, indicates that we should be targeting the parent folder + filename instead of the item itself 284 | // targetContentStream: bool, indicates we should append /content to the item URL 285 | generateGraphUrl: function(driveItem, targetParentFolder, itemRelativeApiPath) { 286 | var url = this.microsoftGraphApiRoot; 287 | if (targetParentFolder) 288 | { 289 | url += "drives/" + driveItem.parentReference.driveId + "/items/" +driveItem.parentReference.id + "/children/" + driveItem.name; 290 | } else { 291 | url += "drives/" + driveItem.parentReference.driveId + "/items/" + driveItem.id; 292 | } 293 | 294 | if (itemRelativeApiPath) { 295 | url += itemRelativeApiPath; 296 | } 297 | return url; 298 | }, 299 | 300 | 301 | /************ Create New File *************/ 302 | 303 | // Clear the current editor buffer and reset any local state so we don't 304 | // overwrite an existing file by mistake. 305 | createNewFile: function () { 306 | this.lastSelectedFile = null; 307 | this.openFileID = ""; 308 | this.setFilename(this.defaultFileName); 309 | $("#canvas").attr("disabled", false); 310 | this.setEditorBody(""); 311 | }, 312 | 313 | 314 | /************ Utility functions *************/ 315 | 316 | // Update the state of the editor with a new filename. 317 | setFilename: function (filename) { 318 | var btnRename = this.buttons["rename"]; 319 | if (btnRename) { 320 | $(btnRename).text(filename); 321 | } 322 | }, 323 | 324 | // Set the contents of the editor to a new value. 325 | setEditorBody: function (text) { 326 | $("#canvas").val(text); 327 | }, 328 | 329 | // State and function to connect elements in the HTML page to actions in the markdown editor. 330 | buttons: {}, 331 | wireUpCommandButton: function(element, cmd) 332 | { 333 | this.buttons[cmd] = element; 334 | switch(cmd) { 335 | case "new": 336 | element.onclick = function () { markdownEditor.createNewFile(); return false; } 337 | break; 338 | case "open": 339 | element.onclick = function () { markdownEditor.openFile(); return false; } 340 | break; 341 | case "save": 342 | element.onclick = function () { markdownEditor.saveFile(); return false; } 343 | break; 344 | case "saveAs": 345 | element.onclick = function () { markdownEditor.saveAsFile(); return false; } 346 | break; 347 | case "rename": 348 | element.onclick = function () { markdownEditor.renameFile(); return false; } 349 | break; 350 | case "share": 351 | element.onclick = function () { markdownEditor.shareFile(); return false; } 352 | break; 353 | } 354 | }, 355 | 356 | // Handle displaying errors to the user 357 | showError: function (msg, e) { 358 | window.alert(msg); 359 | }, 360 | 361 | showSuccessMessage: function(msg) { 362 | window.alert(msg); 363 | }, 364 | 365 | // An object representing the currently selected file 366 | lastSelectedFile: null, 367 | 368 | // The access_token returned from the picker so we can make API calls again. 369 | accessToken: null, 370 | 371 | user: { 372 | id: "nouser@contoso.com", 373 | domain: "organizations" 374 | } 375 | } 376 | 377 | $("#canvas").attr("disabled", true); 378 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | OneDrive Text Editor - Sample Code 2 | Copyright (c) Microsoft Corporation 3 | All rights reserved. 4 | 5 | MIT License 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | this software and associated documentation files (the ""Software""), to deal in 9 | the Software without restriction, including without limitation the rights to use, 10 | copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the 11 | Software, and to permit persons to whom the Software is furnished to do so, 12 | subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 18 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 19 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # OneDrive Text Editor Sample 2 | 3 | This sample application provides a simple markdown (text) editor experience for files stored in OneDrive. 4 | 5 | It demonstrates the following: 6 | 7 | * Using the OneDrive file picker to select files from OneDrive personal and OneDrive for Business. 8 | * Downloading the contents of a file from OneDrive 9 | * Saving a file back to OneDrive 10 | * Using the Microsoft Graph to retrieve a sharing link 11 | 12 | This is written as a single-page JavaScript application and can be hosted on any HTTPS compatible server. 13 | 14 | ## App Registration 15 | 16 | To register an app to use the [v7 OneDrive Picker](https://dev.onedrive.com/sdk/js-v7/js-picker-overview.htm) visit the [Microsoft Apps Registration Page](https://apps.dev.microsoft.com). 17 | -------------------------------------------------------------------------------- /start-iis.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | "%programfiles%\IIS Express\iisexpress.exe" /path:"%CD%" /port:9999 3 | --------------------------------------------------------------------------------