ZLMRTCClient.js 299 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466
  1. var ZLMRTCClient = (function (exports) {
  2. 'use strict';
  3. const Events$1 = {
  4. WEBRTC_NOT_SUPPORT: 'WEBRTC_NOT_SUPPORT',
  5. WEBRTC_ICE_CANDIDATE_ERROR: 'WEBRTC_ICE_CANDIDATE_ERROR',
  6. WEBRTC_OFFER_ANWSER_EXCHANGE_FAILED: 'WEBRTC_OFFER_ANWSER_EXCHANGE_FAILED',
  7. WEBRTC_ON_REMOTE_STREAMS: 'WEBRTC_ON_REMOTE_STREAMS',
  8. WEBRTC_ON_LOCAL_STREAM: 'WEBRTC_ON_LOCAL_STREAM',
  9. WEBRTC_ON_CONNECTION_STATE_CHANGE: 'WEBRTC_ON_CONNECTION_STATE_CHANGE',
  10. WEBRTC_ON_DATA_CHANNEL_OPEN: 'WEBRTC_ON_DATA_CHANNEL_OPEN',
  11. WEBRTC_ON_DATA_CHANNEL_CLOSE: 'WEBRTC_ON_DATA_CHANNEL_CLOSE',
  12. WEBRTC_ON_DATA_CHANNEL_ERR: 'WEBRTC_ON_DATA_CHANNEL_ERR',
  13. WEBRTC_ON_DATA_CHANNEL_MSG: 'WEBRTC_ON_DATA_CHANNEL_MSG',
  14. CAPTURE_STREAM_FAILED: 'CAPTURE_STREAM_FAILED'
  15. };
  16. const VERSION$1 = '1.1.0';
  17. const BUILD_DATE = 'Thu Jun 20 2024 16:15:41 GMT+0800 (China Standard Time)';
  18. // Copyright (C) <2018> Intel Corporation
  19. //
  20. // SPDX-License-Identifier: Apache-2.0
  21. // eslint-disable-next-line require-jsdoc
  22. function isFirefox() {
  23. return window.navigator.userAgent.match('Firefox') !== null;
  24. }
  25. // eslint-disable-next-line require-jsdoc
  26. function isChrome() {
  27. return window.navigator.userAgent.match('Chrome') !== null;
  28. }
  29. // eslint-disable-next-line require-jsdoc
  30. function isEdge() {
  31. return window.navigator.userAgent.match(/Edge\/(\d+).(\d+)$/) !== null;
  32. }
  33. // Copyright (C) <2018> Intel Corporation
  34. /**
  35. * @class AudioSourceInfo
  36. * @classDesc Source info about an audio track. Values: 'mic', 'screen-cast', 'file', 'mixed'.
  37. * @memberOf Owt.Base
  38. * @readonly
  39. * @enum {string}
  40. */
  41. const AudioSourceInfo = {
  42. MIC: 'mic',
  43. SCREENCAST: 'screen-cast',
  44. FILE: 'file',
  45. MIXED: 'mixed'
  46. };
  47. /**
  48. * @class VideoSourceInfo
  49. * @classDesc Source info about a video track. Values: 'camera', 'screen-cast', 'file', 'mixed'.
  50. * @memberOf Owt.Base
  51. * @readonly
  52. * @enum {string}
  53. */
  54. const VideoSourceInfo = {
  55. CAMERA: 'camera',
  56. SCREENCAST: 'screen-cast',
  57. FILE: 'file',
  58. MIXED: 'mixed'
  59. };
  60. /**
  61. * @class TrackKind
  62. * @classDesc Kind of a track. Values: 'audio' for audio track, 'video' for video track, 'av' for both audio and video tracks.
  63. * @memberOf Owt.Base
  64. * @readonly
  65. * @enum {string}
  66. */
  67. const TrackKind = {
  68. /**
  69. * Audio tracks.
  70. * @type string
  71. */
  72. AUDIO: 'audio',
  73. /**
  74. * Video tracks.
  75. * @type string
  76. */
  77. VIDEO: 'video',
  78. /**
  79. * Both audio and video tracks.
  80. * @type string
  81. */
  82. AUDIO_AND_VIDEO: 'av'
  83. };
  84. /**
  85. * @class Resolution
  86. * @memberOf Owt.Base
  87. * @classDesc The Resolution defines the size of a rectangle.
  88. * @constructor
  89. * @param {number} width
  90. * @param {number} height
  91. */
  92. class Resolution {
  93. // eslint-disable-next-line require-jsdoc
  94. constructor(width, height) {
  95. /**
  96. * @member {number} width
  97. * @instance
  98. * @memberof Owt.Base.Resolution
  99. */
  100. this.width = width;
  101. /**
  102. * @member {number} height
  103. * @instance
  104. * @memberof Owt.Base.Resolution
  105. */
  106. this.height = height;
  107. }
  108. }
  109. /*
  110. * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
  111. *
  112. * Use of this source code is governed by a BSD-style license
  113. * that can be found in the LICENSE file in the root of the source
  114. * tree.
  115. */
  116. let logDisabled_ = true;
  117. let deprecationWarnings_ = true;
  118. /**
  119. * Extract browser version out of the provided user agent string.
  120. *
  121. * @param {!string} uastring userAgent string.
  122. * @param {!string} expr Regular expression used as match criteria.
  123. * @param {!number} pos position in the version string to be returned.
  124. * @return {!number} browser version.
  125. */
  126. function extractVersion(uastring, expr, pos) {
  127. const match = uastring.match(expr);
  128. return match && match.length >= pos && parseInt(match[pos], 10);
  129. }
  130. // Wraps the peerconnection event eventNameToWrap in a function
  131. // which returns the modified event object (or false to prevent
  132. // the event).
  133. function wrapPeerConnectionEvent(window, eventNameToWrap, wrapper) {
  134. if (!window.RTCPeerConnection) {
  135. return;
  136. }
  137. const proto = window.RTCPeerConnection.prototype;
  138. const nativeAddEventListener = proto.addEventListener;
  139. proto.addEventListener = function(nativeEventName, cb) {
  140. if (nativeEventName !== eventNameToWrap) {
  141. return nativeAddEventListener.apply(this, arguments);
  142. }
  143. const wrappedCallback = (e) => {
  144. const modifiedEvent = wrapper(e);
  145. if (modifiedEvent) {
  146. if (cb.handleEvent) {
  147. cb.handleEvent(modifiedEvent);
  148. } else {
  149. cb(modifiedEvent);
  150. }
  151. }
  152. };
  153. this._eventMap = this._eventMap || {};
  154. if (!this._eventMap[eventNameToWrap]) {
  155. this._eventMap[eventNameToWrap] = new Map();
  156. }
  157. this._eventMap[eventNameToWrap].set(cb, wrappedCallback);
  158. return nativeAddEventListener.apply(this, [nativeEventName,
  159. wrappedCallback]);
  160. };
  161. const nativeRemoveEventListener = proto.removeEventListener;
  162. proto.removeEventListener = function(nativeEventName, cb) {
  163. if (nativeEventName !== eventNameToWrap || !this._eventMap
  164. || !this._eventMap[eventNameToWrap]) {
  165. return nativeRemoveEventListener.apply(this, arguments);
  166. }
  167. if (!this._eventMap[eventNameToWrap].has(cb)) {
  168. return nativeRemoveEventListener.apply(this, arguments);
  169. }
  170. const unwrappedCb = this._eventMap[eventNameToWrap].get(cb);
  171. this._eventMap[eventNameToWrap].delete(cb);
  172. if (this._eventMap[eventNameToWrap].size === 0) {
  173. delete this._eventMap[eventNameToWrap];
  174. }
  175. if (Object.keys(this._eventMap).length === 0) {
  176. delete this._eventMap;
  177. }
  178. return nativeRemoveEventListener.apply(this, [nativeEventName,
  179. unwrappedCb]);
  180. };
  181. Object.defineProperty(proto, 'on' + eventNameToWrap, {
  182. get() {
  183. return this['_on' + eventNameToWrap];
  184. },
  185. set(cb) {
  186. if (this['_on' + eventNameToWrap]) {
  187. this.removeEventListener(eventNameToWrap,
  188. this['_on' + eventNameToWrap]);
  189. delete this['_on' + eventNameToWrap];
  190. }
  191. if (cb) {
  192. this.addEventListener(eventNameToWrap,
  193. this['_on' + eventNameToWrap] = cb);
  194. }
  195. },
  196. enumerable: true,
  197. configurable: true
  198. });
  199. }
  200. function disableLog(bool) {
  201. if (typeof bool !== 'boolean') {
  202. return new Error('Argument type: ' + typeof bool +
  203. '. Please use a boolean.');
  204. }
  205. logDisabled_ = bool;
  206. return (bool) ? 'adapter.js logging disabled' :
  207. 'adapter.js logging enabled';
  208. }
  209. /**
  210. * Disable or enable deprecation warnings
  211. * @param {!boolean} bool set to true to disable warnings.
  212. */
  213. function disableWarnings(bool) {
  214. if (typeof bool !== 'boolean') {
  215. return new Error('Argument type: ' + typeof bool +
  216. '. Please use a boolean.');
  217. }
  218. deprecationWarnings_ = !bool;
  219. return 'adapter.js deprecation warnings ' + (bool ? 'disabled' : 'enabled');
  220. }
  221. function log$1() {
  222. if (typeof window === 'object') {
  223. if (logDisabled_) {
  224. return;
  225. }
  226. if (typeof console !== 'undefined' && typeof console.log === 'function') {
  227. console.log.apply(console, arguments);
  228. }
  229. }
  230. }
  231. /**
  232. * Shows a deprecation warning suggesting the modern and spec-compatible API.
  233. */
  234. function deprecated(oldMethod, newMethod) {
  235. if (!deprecationWarnings_) {
  236. return;
  237. }
  238. console.warn(oldMethod + ' is deprecated, please use ' + newMethod +
  239. ' instead.');
  240. }
  241. /**
  242. * Browser detector.
  243. *
  244. * @return {object} result containing browser and version
  245. * properties.
  246. */
  247. function detectBrowser(window) {
  248. // Returned result object.
  249. const result = {browser: null, version: null};
  250. // Fail early if it's not a browser
  251. if (typeof window === 'undefined' || !window.navigator) {
  252. result.browser = 'Not a browser.';
  253. return result;
  254. }
  255. const {navigator} = window;
  256. if (navigator.mozGetUserMedia) { // Firefox.
  257. result.browser = 'firefox';
  258. result.version = extractVersion(navigator.userAgent,
  259. /Firefox\/(\d+)\./, 1);
  260. } else if (navigator.webkitGetUserMedia ||
  261. (window.isSecureContext === false && window.webkitRTCPeerConnection &&
  262. !window.RTCIceGatherer)) {
  263. // Chrome, Chromium, Webview, Opera.
  264. // Version matches Chrome/WebRTC version.
  265. // Chrome 74 removed webkitGetUserMedia on http as well so we need the
  266. // more complicated fallback to webkitRTCPeerConnection.
  267. result.browser = 'chrome';
  268. result.version = extractVersion(navigator.userAgent,
  269. /Chrom(e|ium)\/(\d+)\./, 2);
  270. } else if (navigator.mediaDevices &&
  271. navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)) { // Edge.
  272. result.browser = 'edge';
  273. result.version = extractVersion(navigator.userAgent,
  274. /Edge\/(\d+).(\d+)$/, 2);
  275. } else if (window.RTCPeerConnection &&
  276. navigator.userAgent.match(/AppleWebKit\/(\d+)\./)) { // Safari.
  277. result.browser = 'safari';
  278. result.version = extractVersion(navigator.userAgent,
  279. /AppleWebKit\/(\d+)\./, 1);
  280. result.supportsUnifiedPlan = window.RTCRtpTransceiver &&
  281. 'currentDirection' in window.RTCRtpTransceiver.prototype;
  282. } else { // Default fallthrough: not supported.
  283. result.browser = 'Not a supported browser.';
  284. return result;
  285. }
  286. return result;
  287. }
  288. /**
  289. * Checks if something is an object.
  290. *
  291. * @param {*} val The something you want to check.
  292. * @return true if val is an object, false otherwise.
  293. */
  294. function isObject$1(val) {
  295. return Object.prototype.toString.call(val) === '[object Object]';
  296. }
  297. /**
  298. * Remove all empty objects and undefined values
  299. * from a nested object -- an enhanced and vanilla version
  300. * of Lodash's `compact`.
  301. */
  302. function compactObject(data) {
  303. if (!isObject$1(data)) {
  304. return data;
  305. }
  306. return Object.keys(data).reduce(function(accumulator, key) {
  307. const isObj = isObject$1(data[key]);
  308. const value = isObj ? compactObject(data[key]) : data[key];
  309. const isEmptyObject = isObj && !Object.keys(value).length;
  310. if (value === undefined || isEmptyObject) {
  311. return accumulator;
  312. }
  313. return Object.assign(accumulator, {[key]: value});
  314. }, {});
  315. }
  316. /* iterates the stats graph recursively. */
  317. function walkStats(stats, base, resultSet) {
  318. if (!base || resultSet.has(base.id)) {
  319. return;
  320. }
  321. resultSet.set(base.id, base);
  322. Object.keys(base).forEach(name => {
  323. if (name.endsWith('Id')) {
  324. walkStats(stats, stats.get(base[name]), resultSet);
  325. } else if (name.endsWith('Ids')) {
  326. base[name].forEach(id => {
  327. walkStats(stats, stats.get(id), resultSet);
  328. });
  329. }
  330. });
  331. }
  332. /* filter getStats for a sender/receiver track. */
  333. function filterStats(result, track, outbound) {
  334. const streamStatsType = outbound ? 'outbound-rtp' : 'inbound-rtp';
  335. const filteredResult = new Map();
  336. if (track === null) {
  337. return filteredResult;
  338. }
  339. const trackStats = [];
  340. result.forEach(value => {
  341. if (value.type === 'track' &&
  342. value.trackIdentifier === track.id) {
  343. trackStats.push(value);
  344. }
  345. });
  346. trackStats.forEach(trackStat => {
  347. result.forEach(stats => {
  348. if (stats.type === streamStatsType && stats.trackId === trackStat.id) {
  349. walkStats(result, stats, filteredResult);
  350. }
  351. });
  352. });
  353. return filteredResult;
  354. }
  355. /*
  356. * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
  357. *
  358. * Use of this source code is governed by a BSD-style license
  359. * that can be found in the LICENSE file in the root of the source
  360. * tree.
  361. */
  362. const logging = log$1;
  363. function shimGetUserMedia$3(window, browserDetails) {
  364. const navigator = window && window.navigator;
  365. if (!navigator.mediaDevices) {
  366. return;
  367. }
  368. const constraintsToChrome_ = function(c) {
  369. if (typeof c !== 'object' || c.mandatory || c.optional) {
  370. return c;
  371. }
  372. const cc = {};
  373. Object.keys(c).forEach(key => {
  374. if (key === 'require' || key === 'advanced' || key === 'mediaSource') {
  375. return;
  376. }
  377. const r = (typeof c[key] === 'object') ? c[key] : {ideal: c[key]};
  378. if (r.exact !== undefined && typeof r.exact === 'number') {
  379. r.min = r.max = r.exact;
  380. }
  381. const oldname_ = function(prefix, name) {
  382. if (prefix) {
  383. return prefix + name.charAt(0).toUpperCase() + name.slice(1);
  384. }
  385. return (name === 'deviceId') ? 'sourceId' : name;
  386. };
  387. if (r.ideal !== undefined) {
  388. cc.optional = cc.optional || [];
  389. let oc = {};
  390. if (typeof r.ideal === 'number') {
  391. oc[oldname_('min', key)] = r.ideal;
  392. cc.optional.push(oc);
  393. oc = {};
  394. oc[oldname_('max', key)] = r.ideal;
  395. cc.optional.push(oc);
  396. } else {
  397. oc[oldname_('', key)] = r.ideal;
  398. cc.optional.push(oc);
  399. }
  400. }
  401. if (r.exact !== undefined && typeof r.exact !== 'number') {
  402. cc.mandatory = cc.mandatory || {};
  403. cc.mandatory[oldname_('', key)] = r.exact;
  404. } else {
  405. ['min', 'max'].forEach(mix => {
  406. if (r[mix] !== undefined) {
  407. cc.mandatory = cc.mandatory || {};
  408. cc.mandatory[oldname_(mix, key)] = r[mix];
  409. }
  410. });
  411. }
  412. });
  413. if (c.advanced) {
  414. cc.optional = (cc.optional || []).concat(c.advanced);
  415. }
  416. return cc;
  417. };
  418. const shimConstraints_ = function(constraints, func) {
  419. if (browserDetails.version >= 61) {
  420. return func(constraints);
  421. }
  422. constraints = JSON.parse(JSON.stringify(constraints));
  423. if (constraints && typeof constraints.audio === 'object') {
  424. const remap = function(obj, a, b) {
  425. if (a in obj && !(b in obj)) {
  426. obj[b] = obj[a];
  427. delete obj[a];
  428. }
  429. };
  430. constraints = JSON.parse(JSON.stringify(constraints));
  431. remap(constraints.audio, 'autoGainControl', 'googAutoGainControl');
  432. remap(constraints.audio, 'noiseSuppression', 'googNoiseSuppression');
  433. constraints.audio = constraintsToChrome_(constraints.audio);
  434. }
  435. if (constraints && typeof constraints.video === 'object') {
  436. // Shim facingMode for mobile & surface pro.
  437. let face = constraints.video.facingMode;
  438. face = face && ((typeof face === 'object') ? face : {ideal: face});
  439. const getSupportedFacingModeLies = browserDetails.version < 66;
  440. if ((face && (face.exact === 'user' || face.exact === 'environment' ||
  441. face.ideal === 'user' || face.ideal === 'environment')) &&
  442. !(navigator.mediaDevices.getSupportedConstraints &&
  443. navigator.mediaDevices.getSupportedConstraints().facingMode &&
  444. !getSupportedFacingModeLies)) {
  445. delete constraints.video.facingMode;
  446. let matches;
  447. if (face.exact === 'environment' || face.ideal === 'environment') {
  448. matches = ['back', 'rear'];
  449. } else if (face.exact === 'user' || face.ideal === 'user') {
  450. matches = ['front'];
  451. }
  452. if (matches) {
  453. // Look for matches in label, or use last cam for back (typical).
  454. return navigator.mediaDevices.enumerateDevices()
  455. .then(devices => {
  456. devices = devices.filter(d => d.kind === 'videoinput');
  457. let dev = devices.find(d => matches.some(match =>
  458. d.label.toLowerCase().includes(match)));
  459. if (!dev && devices.length && matches.includes('back')) {
  460. dev = devices[devices.length - 1]; // more likely the back cam
  461. }
  462. if (dev) {
  463. constraints.video.deviceId = face.exact ? {exact: dev.deviceId} :
  464. {ideal: dev.deviceId};
  465. }
  466. constraints.video = constraintsToChrome_(constraints.video);
  467. logging('chrome: ' + JSON.stringify(constraints));
  468. return func(constraints);
  469. });
  470. }
  471. }
  472. constraints.video = constraintsToChrome_(constraints.video);
  473. }
  474. logging('chrome: ' + JSON.stringify(constraints));
  475. return func(constraints);
  476. };
  477. const shimError_ = function(e) {
  478. if (browserDetails.version >= 64) {
  479. return e;
  480. }
  481. return {
  482. name: {
  483. PermissionDeniedError: 'NotAllowedError',
  484. PermissionDismissedError: 'NotAllowedError',
  485. InvalidStateError: 'NotAllowedError',
  486. DevicesNotFoundError: 'NotFoundError',
  487. ConstraintNotSatisfiedError: 'OverconstrainedError',
  488. TrackStartError: 'NotReadableError',
  489. MediaDeviceFailedDueToShutdown: 'NotAllowedError',
  490. MediaDeviceKillSwitchOn: 'NotAllowedError',
  491. TabCaptureError: 'AbortError',
  492. ScreenCaptureError: 'AbortError',
  493. DeviceCaptureError: 'AbortError'
  494. }[e.name] || e.name,
  495. message: e.message,
  496. constraint: e.constraint || e.constraintName,
  497. toString() {
  498. return this.name + (this.message && ': ') + this.message;
  499. }
  500. };
  501. };
  502. const getUserMedia_ = function(constraints, onSuccess, onError) {
  503. shimConstraints_(constraints, c => {
  504. navigator.webkitGetUserMedia(c, onSuccess, e => {
  505. if (onError) {
  506. onError(shimError_(e));
  507. }
  508. });
  509. });
  510. };
  511. navigator.getUserMedia = getUserMedia_.bind(navigator);
  512. // Even though Chrome 45 has navigator.mediaDevices and a getUserMedia
  513. // function which returns a Promise, it does not accept spec-style
  514. // constraints.
  515. if (navigator.mediaDevices.getUserMedia) {
  516. const origGetUserMedia = navigator.mediaDevices.getUserMedia.
  517. bind(navigator.mediaDevices);
  518. navigator.mediaDevices.getUserMedia = function(cs) {
  519. return shimConstraints_(cs, c => origGetUserMedia(c).then(stream => {
  520. if (c.audio && !stream.getAudioTracks().length ||
  521. c.video && !stream.getVideoTracks().length) {
  522. stream.getTracks().forEach(track => {
  523. track.stop();
  524. });
  525. throw new DOMException('', 'NotFoundError');
  526. }
  527. return stream;
  528. }, e => Promise.reject(shimError_(e))));
  529. };
  530. }
  531. }
  532. /*
  533. * Copyright (c) 2018 The adapter.js project authors. All Rights Reserved.
  534. *
  535. * Use of this source code is governed by a BSD-style license
  536. * that can be found in the LICENSE file in the root of the source
  537. * tree.
  538. */
  539. function shimGetDisplayMedia$2(window, getSourceId) {
  540. if (window.navigator.mediaDevices &&
  541. 'getDisplayMedia' in window.navigator.mediaDevices) {
  542. return;
  543. }
  544. if (!(window.navigator.mediaDevices)) {
  545. return;
  546. }
  547. // getSourceId is a function that returns a promise resolving with
  548. // the sourceId of the screen/window/tab to be shared.
  549. if (typeof getSourceId !== 'function') {
  550. console.error('shimGetDisplayMedia: getSourceId argument is not ' +
  551. 'a function');
  552. return;
  553. }
  554. window.navigator.mediaDevices.getDisplayMedia =
  555. function getDisplayMedia(constraints) {
  556. return getSourceId(constraints)
  557. .then(sourceId => {
  558. const widthSpecified = constraints.video && constraints.video.width;
  559. const heightSpecified = constraints.video &&
  560. constraints.video.height;
  561. const frameRateSpecified = constraints.video &&
  562. constraints.video.frameRate;
  563. constraints.video = {
  564. mandatory: {
  565. chromeMediaSource: 'desktop',
  566. chromeMediaSourceId: sourceId,
  567. maxFrameRate: frameRateSpecified || 3
  568. }
  569. };
  570. if (widthSpecified) {
  571. constraints.video.mandatory.maxWidth = widthSpecified;
  572. }
  573. if (heightSpecified) {
  574. constraints.video.mandatory.maxHeight = heightSpecified;
  575. }
  576. return window.navigator.mediaDevices.getUserMedia(constraints);
  577. });
  578. };
  579. }
  580. /*
  581. * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
  582. *
  583. * Use of this source code is governed by a BSD-style license
  584. * that can be found in the LICENSE file in the root of the source
  585. * tree.
  586. */
  587. function shimMediaStream(window) {
  588. window.MediaStream = window.MediaStream || window.webkitMediaStream;
  589. }
  590. function shimOnTrack$1(window) {
  591. if (typeof window === 'object' && window.RTCPeerConnection && !('ontrack' in
  592. window.RTCPeerConnection.prototype)) {
  593. Object.defineProperty(window.RTCPeerConnection.prototype, 'ontrack', {
  594. get() {
  595. return this._ontrack;
  596. },
  597. set(f) {
  598. if (this._ontrack) {
  599. this.removeEventListener('track', this._ontrack);
  600. }
  601. this.addEventListener('track', this._ontrack = f);
  602. },
  603. enumerable: true,
  604. configurable: true
  605. });
  606. const origSetRemoteDescription =
  607. window.RTCPeerConnection.prototype.setRemoteDescription;
  608. window.RTCPeerConnection.prototype.setRemoteDescription =
  609. function setRemoteDescription() {
  610. if (!this._ontrackpoly) {
  611. this._ontrackpoly = (e) => {
  612. // onaddstream does not fire when a track is added to an existing
  613. // stream. But stream.onaddtrack is implemented so we use that.
  614. e.stream.addEventListener('addtrack', te => {
  615. let receiver;
  616. if (window.RTCPeerConnection.prototype.getReceivers) {
  617. receiver = this.getReceivers()
  618. .find(r => r.track && r.track.id === te.track.id);
  619. } else {
  620. receiver = {track: te.track};
  621. }
  622. const event = new Event('track');
  623. event.track = te.track;
  624. event.receiver = receiver;
  625. event.transceiver = {receiver};
  626. event.streams = [e.stream];
  627. this.dispatchEvent(event);
  628. });
  629. e.stream.getTracks().forEach(track => {
  630. let receiver;
  631. if (window.RTCPeerConnection.prototype.getReceivers) {
  632. receiver = this.getReceivers()
  633. .find(r => r.track && r.track.id === track.id);
  634. } else {
  635. receiver = {track};
  636. }
  637. const event = new Event('track');
  638. event.track = track;
  639. event.receiver = receiver;
  640. event.transceiver = {receiver};
  641. event.streams = [e.stream];
  642. this.dispatchEvent(event);
  643. });
  644. };
  645. this.addEventListener('addstream', this._ontrackpoly);
  646. }
  647. return origSetRemoteDescription.apply(this, arguments);
  648. };
  649. } else {
  650. // even if RTCRtpTransceiver is in window, it is only used and
  651. // emitted in unified-plan. Unfortunately this means we need
  652. // to unconditionally wrap the event.
  653. wrapPeerConnectionEvent(window, 'track', e => {
  654. if (!e.transceiver) {
  655. Object.defineProperty(e, 'transceiver',
  656. {value: {receiver: e.receiver}});
  657. }
  658. return e;
  659. });
  660. }
  661. }
  662. function shimGetSendersWithDtmf(window) {
  663. // Overrides addTrack/removeTrack, depends on shimAddTrackRemoveTrack.
  664. if (typeof window === 'object' && window.RTCPeerConnection &&
  665. !('getSenders' in window.RTCPeerConnection.prototype) &&
  666. 'createDTMFSender' in window.RTCPeerConnection.prototype) {
  667. const shimSenderWithDtmf = function(pc, track) {
  668. return {
  669. track,
  670. get dtmf() {
  671. if (this._dtmf === undefined) {
  672. if (track.kind === 'audio') {
  673. this._dtmf = pc.createDTMFSender(track);
  674. } else {
  675. this._dtmf = null;
  676. }
  677. }
  678. return this._dtmf;
  679. },
  680. _pc: pc
  681. };
  682. };
  683. // augment addTrack when getSenders is not available.
  684. if (!window.RTCPeerConnection.prototype.getSenders) {
  685. window.RTCPeerConnection.prototype.getSenders = function getSenders() {
  686. this._senders = this._senders || [];
  687. return this._senders.slice(); // return a copy of the internal state.
  688. };
  689. const origAddTrack = window.RTCPeerConnection.prototype.addTrack;
  690. window.RTCPeerConnection.prototype.addTrack =
  691. function addTrack(track, stream) {
  692. let sender = origAddTrack.apply(this, arguments);
  693. if (!sender) {
  694. sender = shimSenderWithDtmf(this, track);
  695. this._senders.push(sender);
  696. }
  697. return sender;
  698. };
  699. const origRemoveTrack = window.RTCPeerConnection.prototype.removeTrack;
  700. window.RTCPeerConnection.prototype.removeTrack =
  701. function removeTrack(sender) {
  702. origRemoveTrack.apply(this, arguments);
  703. const idx = this._senders.indexOf(sender);
  704. if (idx !== -1) {
  705. this._senders.splice(idx, 1);
  706. }
  707. };
  708. }
  709. const origAddStream = window.RTCPeerConnection.prototype.addStream;
  710. window.RTCPeerConnection.prototype.addStream = function addStream(stream) {
  711. this._senders = this._senders || [];
  712. origAddStream.apply(this, [stream]);
  713. stream.getTracks().forEach(track => {
  714. this._senders.push(shimSenderWithDtmf(this, track));
  715. });
  716. };
  717. const origRemoveStream = window.RTCPeerConnection.prototype.removeStream;
  718. window.RTCPeerConnection.prototype.removeStream =
  719. function removeStream(stream) {
  720. this._senders = this._senders || [];
  721. origRemoveStream.apply(this, [stream]);
  722. stream.getTracks().forEach(track => {
  723. const sender = this._senders.find(s => s.track === track);
  724. if (sender) { // remove sender
  725. this._senders.splice(this._senders.indexOf(sender), 1);
  726. }
  727. });
  728. };
  729. } else if (typeof window === 'object' && window.RTCPeerConnection &&
  730. 'getSenders' in window.RTCPeerConnection.prototype &&
  731. 'createDTMFSender' in window.RTCPeerConnection.prototype &&
  732. window.RTCRtpSender &&
  733. !('dtmf' in window.RTCRtpSender.prototype)) {
  734. const origGetSenders = window.RTCPeerConnection.prototype.getSenders;
  735. window.RTCPeerConnection.prototype.getSenders = function getSenders() {
  736. const senders = origGetSenders.apply(this, []);
  737. senders.forEach(sender => sender._pc = this);
  738. return senders;
  739. };
  740. Object.defineProperty(window.RTCRtpSender.prototype, 'dtmf', {
  741. get() {
  742. if (this._dtmf === undefined) {
  743. if (this.track.kind === 'audio') {
  744. this._dtmf = this._pc.createDTMFSender(this.track);
  745. } else {
  746. this._dtmf = null;
  747. }
  748. }
  749. return this._dtmf;
  750. }
  751. });
  752. }
  753. }
  754. function shimGetStats(window) {
  755. if (!window.RTCPeerConnection) {
  756. return;
  757. }
  758. const origGetStats = window.RTCPeerConnection.prototype.getStats;
  759. window.RTCPeerConnection.prototype.getStats = function getStats() {
  760. const [selector, onSucc, onErr] = arguments;
  761. // If selector is a function then we are in the old style stats so just
  762. // pass back the original getStats format to avoid breaking old users.
  763. if (arguments.length > 0 && typeof selector === 'function') {
  764. return origGetStats.apply(this, arguments);
  765. }
  766. // When spec-style getStats is supported, return those when called with
  767. // either no arguments or the selector argument is null.
  768. if (origGetStats.length === 0 && (arguments.length === 0 ||
  769. typeof selector !== 'function')) {
  770. return origGetStats.apply(this, []);
  771. }
  772. const fixChromeStats_ = function(response) {
  773. const standardReport = {};
  774. const reports = response.result();
  775. reports.forEach(report => {
  776. const standardStats = {
  777. id: report.id,
  778. timestamp: report.timestamp,
  779. type: {
  780. localcandidate: 'local-candidate',
  781. remotecandidate: 'remote-candidate'
  782. }[report.type] || report.type
  783. };
  784. report.names().forEach(name => {
  785. standardStats[name] = report.stat(name);
  786. });
  787. standardReport[standardStats.id] = standardStats;
  788. });
  789. return standardReport;
  790. };
  791. // shim getStats with maplike support
  792. const makeMapStats = function(stats) {
  793. return new Map(Object.keys(stats).map(key => [key, stats[key]]));
  794. };
  795. if (arguments.length >= 2) {
  796. const successCallbackWrapper_ = function(response) {
  797. onSucc(makeMapStats(fixChromeStats_(response)));
  798. };
  799. return origGetStats.apply(this, [successCallbackWrapper_,
  800. selector]);
  801. }
  802. // promise-support
  803. return new Promise((resolve, reject) => {
  804. origGetStats.apply(this, [
  805. function(response) {
  806. resolve(makeMapStats(fixChromeStats_(response)));
  807. }, reject]);
  808. }).then(onSucc, onErr);
  809. };
  810. }
  811. function shimSenderReceiverGetStats(window) {
  812. if (!(typeof window === 'object' && window.RTCPeerConnection &&
  813. window.RTCRtpSender && window.RTCRtpReceiver)) {
  814. return;
  815. }
  816. // shim sender stats.
  817. if (!('getStats' in window.RTCRtpSender.prototype)) {
  818. const origGetSenders = window.RTCPeerConnection.prototype.getSenders;
  819. if (origGetSenders) {
  820. window.RTCPeerConnection.prototype.getSenders = function getSenders() {
  821. const senders = origGetSenders.apply(this, []);
  822. senders.forEach(sender => sender._pc = this);
  823. return senders;
  824. };
  825. }
  826. const origAddTrack = window.RTCPeerConnection.prototype.addTrack;
  827. if (origAddTrack) {
  828. window.RTCPeerConnection.prototype.addTrack = function addTrack() {
  829. const sender = origAddTrack.apply(this, arguments);
  830. sender._pc = this;
  831. return sender;
  832. };
  833. }
  834. window.RTCRtpSender.prototype.getStats = function getStats() {
  835. const sender = this;
  836. return this._pc.getStats().then(result =>
  837. /* Note: this will include stats of all senders that
  838. * send a track with the same id as sender.track as
  839. * it is not possible to identify the RTCRtpSender.
  840. */
  841. filterStats(result, sender.track, true));
  842. };
  843. }
  844. // shim receiver stats.
  845. if (!('getStats' in window.RTCRtpReceiver.prototype)) {
  846. const origGetReceivers = window.RTCPeerConnection.prototype.getReceivers;
  847. if (origGetReceivers) {
  848. window.RTCPeerConnection.prototype.getReceivers =
  849. function getReceivers() {
  850. const receivers = origGetReceivers.apply(this, []);
  851. receivers.forEach(receiver => receiver._pc = this);
  852. return receivers;
  853. };
  854. }
  855. wrapPeerConnectionEvent(window, 'track', e => {
  856. e.receiver._pc = e.srcElement;
  857. return e;
  858. });
  859. window.RTCRtpReceiver.prototype.getStats = function getStats() {
  860. const receiver = this;
  861. return this._pc.getStats().then(result =>
  862. filterStats(result, receiver.track, false));
  863. };
  864. }
  865. if (!('getStats' in window.RTCRtpSender.prototype &&
  866. 'getStats' in window.RTCRtpReceiver.prototype)) {
  867. return;
  868. }
  869. // shim RTCPeerConnection.getStats(track).
  870. const origGetStats = window.RTCPeerConnection.prototype.getStats;
  871. window.RTCPeerConnection.prototype.getStats = function getStats() {
  872. if (arguments.length > 0 &&
  873. arguments[0] instanceof window.MediaStreamTrack) {
  874. const track = arguments[0];
  875. let sender;
  876. let receiver;
  877. let err;
  878. this.getSenders().forEach(s => {
  879. if (s.track === track) {
  880. if (sender) {
  881. err = true;
  882. } else {
  883. sender = s;
  884. }
  885. }
  886. });
  887. this.getReceivers().forEach(r => {
  888. if (r.track === track) {
  889. if (receiver) {
  890. err = true;
  891. } else {
  892. receiver = r;
  893. }
  894. }
  895. return r.track === track;
  896. });
  897. if (err || (sender && receiver)) {
  898. return Promise.reject(new DOMException(
  899. 'There are more than one sender or receiver for the track.',
  900. 'InvalidAccessError'));
  901. } else if (sender) {
  902. return sender.getStats();
  903. } else if (receiver) {
  904. return receiver.getStats();
  905. }
  906. return Promise.reject(new DOMException(
  907. 'There is no sender or receiver for the track.',
  908. 'InvalidAccessError'));
  909. }
  910. return origGetStats.apply(this, arguments);
  911. };
  912. }
  913. function shimAddTrackRemoveTrackWithNative(window) {
  914. // shim addTrack/removeTrack with native variants in order to make
  915. // the interactions with legacy getLocalStreams behave as in other browsers.
  916. // Keeps a mapping stream.id => [stream, rtpsenders...]
  917. window.RTCPeerConnection.prototype.getLocalStreams =
  918. function getLocalStreams() {
  919. this._shimmedLocalStreams = this._shimmedLocalStreams || {};
  920. return Object.keys(this._shimmedLocalStreams)
  921. .map(streamId => this._shimmedLocalStreams[streamId][0]);
  922. };
  923. const origAddTrack = window.RTCPeerConnection.prototype.addTrack;
  924. window.RTCPeerConnection.prototype.addTrack =
  925. function addTrack(track, stream) {
  926. if (!stream) {
  927. return origAddTrack.apply(this, arguments);
  928. }
  929. this._shimmedLocalStreams = this._shimmedLocalStreams || {};
  930. const sender = origAddTrack.apply(this, arguments);
  931. if (!this._shimmedLocalStreams[stream.id]) {
  932. this._shimmedLocalStreams[stream.id] = [stream, sender];
  933. } else if (this._shimmedLocalStreams[stream.id].indexOf(sender) === -1) {
  934. this._shimmedLocalStreams[stream.id].push(sender);
  935. }
  936. return sender;
  937. };
  938. const origAddStream = window.RTCPeerConnection.prototype.addStream;
  939. window.RTCPeerConnection.prototype.addStream = function addStream(stream) {
  940. this._shimmedLocalStreams = this._shimmedLocalStreams || {};
  941. stream.getTracks().forEach(track => {
  942. const alreadyExists = this.getSenders().find(s => s.track === track);
  943. if (alreadyExists) {
  944. throw new DOMException('Track already exists.',
  945. 'InvalidAccessError');
  946. }
  947. });
  948. const existingSenders = this.getSenders();
  949. origAddStream.apply(this, arguments);
  950. const newSenders = this.getSenders()
  951. .filter(newSender => existingSenders.indexOf(newSender) === -1);
  952. this._shimmedLocalStreams[stream.id] = [stream].concat(newSenders);
  953. };
  954. const origRemoveStream = window.RTCPeerConnection.prototype.removeStream;
  955. window.RTCPeerConnection.prototype.removeStream =
  956. function removeStream(stream) {
  957. this._shimmedLocalStreams = this._shimmedLocalStreams || {};
  958. delete this._shimmedLocalStreams[stream.id];
  959. return origRemoveStream.apply(this, arguments);
  960. };
  961. const origRemoveTrack = window.RTCPeerConnection.prototype.removeTrack;
  962. window.RTCPeerConnection.prototype.removeTrack =
  963. function removeTrack(sender) {
  964. this._shimmedLocalStreams = this._shimmedLocalStreams || {};
  965. if (sender) {
  966. Object.keys(this._shimmedLocalStreams).forEach(streamId => {
  967. const idx = this._shimmedLocalStreams[streamId].indexOf(sender);
  968. if (idx !== -1) {
  969. this._shimmedLocalStreams[streamId].splice(idx, 1);
  970. }
  971. if (this._shimmedLocalStreams[streamId].length === 1) {
  972. delete this._shimmedLocalStreams[streamId];
  973. }
  974. });
  975. }
  976. return origRemoveTrack.apply(this, arguments);
  977. };
  978. }
  979. function shimAddTrackRemoveTrack(window, browserDetails) {
  980. if (!window.RTCPeerConnection) {
  981. return;
  982. }
  983. // shim addTrack and removeTrack.
  984. if (window.RTCPeerConnection.prototype.addTrack &&
  985. browserDetails.version >= 65) {
  986. return shimAddTrackRemoveTrackWithNative(window);
  987. }
  988. // also shim pc.getLocalStreams when addTrack is shimmed
  989. // to return the original streams.
  990. const origGetLocalStreams = window.RTCPeerConnection.prototype
  991. .getLocalStreams;
  992. window.RTCPeerConnection.prototype.getLocalStreams =
  993. function getLocalStreams() {
  994. const nativeStreams = origGetLocalStreams.apply(this);
  995. this._reverseStreams = this._reverseStreams || {};
  996. return nativeStreams.map(stream => this._reverseStreams[stream.id]);
  997. };
  998. const origAddStream = window.RTCPeerConnection.prototype.addStream;
  999. window.RTCPeerConnection.prototype.addStream = function addStream(stream) {
  1000. this._streams = this._streams || {};
  1001. this._reverseStreams = this._reverseStreams || {};
  1002. stream.getTracks().forEach(track => {
  1003. const alreadyExists = this.getSenders().find(s => s.track === track);
  1004. if (alreadyExists) {
  1005. throw new DOMException('Track already exists.',
  1006. 'InvalidAccessError');
  1007. }
  1008. });
  1009. // Add identity mapping for consistency with addTrack.
  1010. // Unless this is being used with a stream from addTrack.
  1011. if (!this._reverseStreams[stream.id]) {
  1012. const newStream = new window.MediaStream(stream.getTracks());
  1013. this._streams[stream.id] = newStream;
  1014. this._reverseStreams[newStream.id] = stream;
  1015. stream = newStream;
  1016. }
  1017. origAddStream.apply(this, [stream]);
  1018. };
  1019. const origRemoveStream = window.RTCPeerConnection.prototype.removeStream;
  1020. window.RTCPeerConnection.prototype.removeStream =
  1021. function removeStream(stream) {
  1022. this._streams = this._streams || {};
  1023. this._reverseStreams = this._reverseStreams || {};
  1024. origRemoveStream.apply(this, [(this._streams[stream.id] || stream)]);
  1025. delete this._reverseStreams[(this._streams[stream.id] ?
  1026. this._streams[stream.id].id : stream.id)];
  1027. delete this._streams[stream.id];
  1028. };
  1029. window.RTCPeerConnection.prototype.addTrack =
  1030. function addTrack(track, stream) {
  1031. if (this.signalingState === 'closed') {
  1032. throw new DOMException(
  1033. 'The RTCPeerConnection\'s signalingState is \'closed\'.',
  1034. 'InvalidStateError');
  1035. }
  1036. const streams = [].slice.call(arguments, 1);
  1037. if (streams.length !== 1 ||
  1038. !streams[0].getTracks().find(t => t === track)) {
  1039. // this is not fully correct but all we can manage without
  1040. // [[associated MediaStreams]] internal slot.
  1041. throw new DOMException(
  1042. 'The adapter.js addTrack polyfill only supports a single ' +
  1043. ' stream which is associated with the specified track.',
  1044. 'NotSupportedError');
  1045. }
  1046. const alreadyExists = this.getSenders().find(s => s.track === track);
  1047. if (alreadyExists) {
  1048. throw new DOMException('Track already exists.',
  1049. 'InvalidAccessError');
  1050. }
  1051. this._streams = this._streams || {};
  1052. this._reverseStreams = this._reverseStreams || {};
  1053. const oldStream = this._streams[stream.id];
  1054. if (oldStream) {
  1055. // this is using odd Chrome behaviour, use with caution:
  1056. // https://bugs.chromium.org/p/webrtc/issues/detail?id=7815
  1057. // Note: we rely on the high-level addTrack/dtmf shim to
  1058. // create the sender with a dtmf sender.
  1059. oldStream.addTrack(track);
  1060. // Trigger ONN async.
  1061. Promise.resolve().then(() => {
  1062. this.dispatchEvent(new Event('negotiationneeded'));
  1063. });
  1064. } else {
  1065. const newStream = new window.MediaStream([track]);
  1066. this._streams[stream.id] = newStream;
  1067. this._reverseStreams[newStream.id] = stream;
  1068. this.addStream(newStream);
  1069. }
  1070. return this.getSenders().find(s => s.track === track);
  1071. };
  1072. // replace the internal stream id with the external one and
  1073. // vice versa.
  1074. function replaceInternalStreamId(pc, description) {
  1075. let sdp = description.sdp;
  1076. Object.keys(pc._reverseStreams || []).forEach(internalId => {
  1077. const externalStream = pc._reverseStreams[internalId];
  1078. const internalStream = pc._streams[externalStream.id];
  1079. sdp = sdp.replace(new RegExp(internalStream.id, 'g'),
  1080. externalStream.id);
  1081. });
  1082. return new RTCSessionDescription({
  1083. type: description.type,
  1084. sdp
  1085. });
  1086. }
  1087. function replaceExternalStreamId(pc, description) {
  1088. let sdp = description.sdp;
  1089. Object.keys(pc._reverseStreams || []).forEach(internalId => {
  1090. const externalStream = pc._reverseStreams[internalId];
  1091. const internalStream = pc._streams[externalStream.id];
  1092. sdp = sdp.replace(new RegExp(externalStream.id, 'g'),
  1093. internalStream.id);
  1094. });
  1095. return new RTCSessionDescription({
  1096. type: description.type,
  1097. sdp
  1098. });
  1099. }
  1100. ['createOffer', 'createAnswer'].forEach(function(method) {
  1101. const nativeMethod = window.RTCPeerConnection.prototype[method];
  1102. const methodObj = {[method]() {
  1103. const args = arguments;
  1104. const isLegacyCall = arguments.length &&
  1105. typeof arguments[0] === 'function';
  1106. if (isLegacyCall) {
  1107. return nativeMethod.apply(this, [
  1108. (description) => {
  1109. const desc = replaceInternalStreamId(this, description);
  1110. args[0].apply(null, [desc]);
  1111. },
  1112. (err) => {
  1113. if (args[1]) {
  1114. args[1].apply(null, err);
  1115. }
  1116. }, arguments[2]
  1117. ]);
  1118. }
  1119. return nativeMethod.apply(this, arguments)
  1120. .then(description => replaceInternalStreamId(this, description));
  1121. }};
  1122. window.RTCPeerConnection.prototype[method] = methodObj[method];
  1123. });
  1124. const origSetLocalDescription =
  1125. window.RTCPeerConnection.prototype.setLocalDescription;
  1126. window.RTCPeerConnection.prototype.setLocalDescription =
  1127. function setLocalDescription() {
  1128. if (!arguments.length || !arguments[0].type) {
  1129. return origSetLocalDescription.apply(this, arguments);
  1130. }
  1131. arguments[0] = replaceExternalStreamId(this, arguments[0]);
  1132. return origSetLocalDescription.apply(this, arguments);
  1133. };
  1134. // TODO: mangle getStats: https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamstats-streamidentifier
  1135. const origLocalDescription = Object.getOwnPropertyDescriptor(
  1136. window.RTCPeerConnection.prototype, 'localDescription');
  1137. Object.defineProperty(window.RTCPeerConnection.prototype,
  1138. 'localDescription', {
  1139. get() {
  1140. const description = origLocalDescription.get.apply(this);
  1141. if (description.type === '') {
  1142. return description;
  1143. }
  1144. return replaceInternalStreamId(this, description);
  1145. }
  1146. });
  1147. window.RTCPeerConnection.prototype.removeTrack =
  1148. function removeTrack(sender) {
  1149. if (this.signalingState === 'closed') {
  1150. throw new DOMException(
  1151. 'The RTCPeerConnection\'s signalingState is \'closed\'.',
  1152. 'InvalidStateError');
  1153. }
  1154. // We can not yet check for sender instanceof RTCRtpSender
  1155. // since we shim RTPSender. So we check if sender._pc is set.
  1156. if (!sender._pc) {
  1157. throw new DOMException('Argument 1 of RTCPeerConnection.removeTrack ' +
  1158. 'does not implement interface RTCRtpSender.', 'TypeError');
  1159. }
  1160. const isLocal = sender._pc === this;
  1161. if (!isLocal) {
  1162. throw new DOMException('Sender was not created by this connection.',
  1163. 'InvalidAccessError');
  1164. }
  1165. // Search for the native stream the senders track belongs to.
  1166. this._streams = this._streams || {};
  1167. let stream;
  1168. Object.keys(this._streams).forEach(streamid => {
  1169. const hasTrack = this._streams[streamid].getTracks()
  1170. .find(track => sender.track === track);
  1171. if (hasTrack) {
  1172. stream = this._streams[streamid];
  1173. }
  1174. });
  1175. if (stream) {
  1176. if (stream.getTracks().length === 1) {
  1177. // if this is the last track of the stream, remove the stream. This
  1178. // takes care of any shimmed _senders.
  1179. this.removeStream(this._reverseStreams[stream.id]);
  1180. } else {
  1181. // relying on the same odd chrome behaviour as above.
  1182. stream.removeTrack(sender.track);
  1183. }
  1184. this.dispatchEvent(new Event('negotiationneeded'));
  1185. }
  1186. };
  1187. }
  1188. function shimPeerConnection$2(window, browserDetails) {
  1189. if (!window.RTCPeerConnection && window.webkitRTCPeerConnection) {
  1190. // very basic support for old versions.
  1191. window.RTCPeerConnection = window.webkitRTCPeerConnection;
  1192. }
  1193. if (!window.RTCPeerConnection) {
  1194. return;
  1195. }
  1196. // shim implicit creation of RTCSessionDescription/RTCIceCandidate
  1197. if (browserDetails.version < 53) {
  1198. ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']
  1199. .forEach(function(method) {
  1200. const nativeMethod = window.RTCPeerConnection.prototype[method];
  1201. const methodObj = {[method]() {
  1202. arguments[0] = new ((method === 'addIceCandidate') ?
  1203. window.RTCIceCandidate :
  1204. window.RTCSessionDescription)(arguments[0]);
  1205. return nativeMethod.apply(this, arguments);
  1206. }};
  1207. window.RTCPeerConnection.prototype[method] = methodObj[method];
  1208. });
  1209. }
  1210. }
  1211. // Attempt to fix ONN in plan-b mode.
  1212. function fixNegotiationNeeded(window, browserDetails) {
  1213. wrapPeerConnectionEvent(window, 'negotiationneeded', e => {
  1214. const pc = e.target;
  1215. if (browserDetails.version < 72 || (pc.getConfiguration &&
  1216. pc.getConfiguration().sdpSemantics === 'plan-b')) {
  1217. if (pc.signalingState !== 'stable') {
  1218. return;
  1219. }
  1220. }
  1221. return e;
  1222. });
  1223. }
  1224. var chromeShim = /*#__PURE__*/Object.freeze({
  1225. __proto__: null,
  1226. shimMediaStream: shimMediaStream,
  1227. shimOnTrack: shimOnTrack$1,
  1228. shimGetSendersWithDtmf: shimGetSendersWithDtmf,
  1229. shimGetStats: shimGetStats,
  1230. shimSenderReceiverGetStats: shimSenderReceiverGetStats,
  1231. shimAddTrackRemoveTrackWithNative: shimAddTrackRemoveTrackWithNative,
  1232. shimAddTrackRemoveTrack: shimAddTrackRemoveTrack,
  1233. shimPeerConnection: shimPeerConnection$2,
  1234. fixNegotiationNeeded: fixNegotiationNeeded,
  1235. shimGetUserMedia: shimGetUserMedia$3,
  1236. shimGetDisplayMedia: shimGetDisplayMedia$2
  1237. });
  1238. /*
  1239. * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
  1240. *
  1241. * Use of this source code is governed by a BSD-style license
  1242. * that can be found in the LICENSE file in the root of the source
  1243. * tree.
  1244. */
  1245. // Edge does not like
  1246. // 1) stun: filtered after 14393 unless ?transport=udp is present
  1247. // 2) turn: that does not have all of turn:host:port?transport=udp
  1248. // 3) turn: with ipv6 addresses
  1249. // 4) turn: occurring muliple times
  1250. function filterIceServers$1(iceServers, edgeVersion) {
  1251. let hasTurn = false;
  1252. iceServers = JSON.parse(JSON.stringify(iceServers));
  1253. return iceServers.filter(server => {
  1254. if (server && (server.urls || server.url)) {
  1255. let urls = server.urls || server.url;
  1256. if (server.url && !server.urls) {
  1257. deprecated('RTCIceServer.url', 'RTCIceServer.urls');
  1258. }
  1259. const isString = typeof urls === 'string';
  1260. if (isString) {
  1261. urls = [urls];
  1262. }
  1263. urls = urls.filter(url => {
  1264. // filter STUN unconditionally.
  1265. if (url.indexOf('stun:') === 0) {
  1266. return false;
  1267. }
  1268. const validTurn = url.startsWith('turn') &&
  1269. !url.startsWith('turn:[') &&
  1270. url.includes('transport=udp');
  1271. if (validTurn && !hasTurn) {
  1272. hasTurn = true;
  1273. return true;
  1274. }
  1275. return validTurn && !hasTurn;
  1276. });
  1277. delete server.url;
  1278. server.urls = isString ? urls[0] : urls;
  1279. return !!urls.length;
  1280. }
  1281. });
  1282. }
  1283. var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
  1284. function createCommonjsModule(fn) {
  1285. var module = { exports: {} };
  1286. return fn(module, module.exports), module.exports;
  1287. }
  1288. function commonjsRequire (path) {
  1289. throw new Error('Could not dynamically require "' + path + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.');
  1290. }
  1291. /* eslint-env node */
  1292. var sdp = createCommonjsModule(function (module) {
  1293. // SDP helpers.
  1294. var SDPUtils = {};
  1295. // Generate an alphanumeric identifier for cname or mids.
  1296. // TODO: use UUIDs instead? https://gist.github.com/jed/982883
  1297. SDPUtils.generateIdentifier = function() {
  1298. return Math.random().toString(36).substr(2, 10);
  1299. };
  1300. // The RTCP CNAME used by all peerconnections from the same JS.
  1301. SDPUtils.localCName = SDPUtils.generateIdentifier();
  1302. // Splits SDP into lines, dealing with both CRLF and LF.
  1303. SDPUtils.splitLines = function(blob) {
  1304. return blob.trim().split('\n').map(function(line) {
  1305. return line.trim();
  1306. });
  1307. };
  1308. // Splits SDP into sessionpart and mediasections. Ensures CRLF.
  1309. SDPUtils.splitSections = function(blob) {
  1310. var parts = blob.split('\nm=');
  1311. return parts.map(function(part, index) {
  1312. return (index > 0 ? 'm=' + part : part).trim() + '\r\n';
  1313. });
  1314. };
  1315. // returns the session description.
  1316. SDPUtils.getDescription = function(blob) {
  1317. var sections = SDPUtils.splitSections(blob);
  1318. return sections && sections[0];
  1319. };
  1320. // returns the individual media sections.
  1321. SDPUtils.getMediaSections = function(blob) {
  1322. var sections = SDPUtils.splitSections(blob);
  1323. sections.shift();
  1324. return sections;
  1325. };
  1326. // Returns lines that start with a certain prefix.
  1327. SDPUtils.matchPrefix = function(blob, prefix) {
  1328. return SDPUtils.splitLines(blob).filter(function(line) {
  1329. return line.indexOf(prefix) === 0;
  1330. });
  1331. };
  1332. // Parses an ICE candidate line. Sample input:
  1333. // candidate:702786350 2 udp 41819902 8.8.8.8 60769 typ relay raddr 8.8.8.8
  1334. // rport 55996"
  1335. SDPUtils.parseCandidate = function(line) {
  1336. var parts;
  1337. // Parse both variants.
  1338. if (line.indexOf('a=candidate:') === 0) {
  1339. parts = line.substring(12).split(' ');
  1340. } else {
  1341. parts = line.substring(10).split(' ');
  1342. }
  1343. var candidate = {
  1344. foundation: parts[0],
  1345. component: parseInt(parts[1], 10),
  1346. protocol: parts[2].toLowerCase(),
  1347. priority: parseInt(parts[3], 10),
  1348. ip: parts[4],
  1349. address: parts[4], // address is an alias for ip.
  1350. port: parseInt(parts[5], 10),
  1351. // skip parts[6] == 'typ'
  1352. type: parts[7]
  1353. };
  1354. for (var i = 8; i < parts.length; i += 2) {
  1355. switch (parts[i]) {
  1356. case 'raddr':
  1357. candidate.relatedAddress = parts[i + 1];
  1358. break;
  1359. case 'rport':
  1360. candidate.relatedPort = parseInt(parts[i + 1], 10);
  1361. break;
  1362. case 'tcptype':
  1363. candidate.tcpType = parts[i + 1];
  1364. break;
  1365. case 'ufrag':
  1366. candidate.ufrag = parts[i + 1]; // for backward compability.
  1367. candidate.usernameFragment = parts[i + 1];
  1368. break;
  1369. default: // extension handling, in particular ufrag
  1370. candidate[parts[i]] = parts[i + 1];
  1371. break;
  1372. }
  1373. }
  1374. return candidate;
  1375. };
  1376. // Translates a candidate object into SDP candidate attribute.
  1377. SDPUtils.writeCandidate = function(candidate) {
  1378. var sdp = [];
  1379. sdp.push(candidate.foundation);
  1380. sdp.push(candidate.component);
  1381. sdp.push(candidate.protocol.toUpperCase());
  1382. sdp.push(candidate.priority);
  1383. sdp.push(candidate.address || candidate.ip);
  1384. sdp.push(candidate.port);
  1385. var type = candidate.type;
  1386. sdp.push('typ');
  1387. sdp.push(type);
  1388. if (type !== 'host' && candidate.relatedAddress &&
  1389. candidate.relatedPort) {
  1390. sdp.push('raddr');
  1391. sdp.push(candidate.relatedAddress);
  1392. sdp.push('rport');
  1393. sdp.push(candidate.relatedPort);
  1394. }
  1395. if (candidate.tcpType && candidate.protocol.toLowerCase() === 'tcp') {
  1396. sdp.push('tcptype');
  1397. sdp.push(candidate.tcpType);
  1398. }
  1399. if (candidate.usernameFragment || candidate.ufrag) {
  1400. sdp.push('ufrag');
  1401. sdp.push(candidate.usernameFragment || candidate.ufrag);
  1402. }
  1403. return 'candidate:' + sdp.join(' ');
  1404. };
  1405. // Parses an ice-options line, returns an array of option tags.
  1406. // a=ice-options:foo bar
  1407. SDPUtils.parseIceOptions = function(line) {
  1408. return line.substr(14).split(' ');
  1409. };
  1410. // Parses an rtpmap line, returns RTCRtpCoddecParameters. Sample input:
  1411. // a=rtpmap:111 opus/48000/2
  1412. SDPUtils.parseRtpMap = function(line) {
  1413. var parts = line.substr(9).split(' ');
  1414. var parsed = {
  1415. payloadType: parseInt(parts.shift(), 10) // was: id
  1416. };
  1417. parts = parts[0].split('/');
  1418. parsed.name = parts[0];
  1419. parsed.clockRate = parseInt(parts[1], 10); // was: clockrate
  1420. parsed.channels = parts.length === 3 ? parseInt(parts[2], 10) : 1;
  1421. // legacy alias, got renamed back to channels in ORTC.
  1422. parsed.numChannels = parsed.channels;
  1423. return parsed;
  1424. };
  1425. // Generate an a=rtpmap line from RTCRtpCodecCapability or
  1426. // RTCRtpCodecParameters.
  1427. SDPUtils.writeRtpMap = function(codec) {
  1428. var pt = codec.payloadType;
  1429. if (codec.preferredPayloadType !== undefined) {
  1430. pt = codec.preferredPayloadType;
  1431. }
  1432. var channels = codec.channels || codec.numChannels || 1;
  1433. return 'a=rtpmap:' + pt + ' ' + codec.name + '/' + codec.clockRate +
  1434. (channels !== 1 ? '/' + channels : '') + '\r\n';
  1435. };
  1436. // Parses an a=extmap line (headerextension from RFC 5285). Sample input:
  1437. // a=extmap:2 urn:ietf:params:rtp-hdrext:toffset
  1438. // a=extmap:2/sendonly urn:ietf:params:rtp-hdrext:toffset
  1439. SDPUtils.parseExtmap = function(line) {
  1440. var parts = line.substr(9).split(' ');
  1441. return {
  1442. id: parseInt(parts[0], 10),
  1443. direction: parts[0].indexOf('/') > 0 ? parts[0].split('/')[1] : 'sendrecv',
  1444. uri: parts[1]
  1445. };
  1446. };
  1447. // Generates a=extmap line from RTCRtpHeaderExtensionParameters or
  1448. // RTCRtpHeaderExtension.
  1449. SDPUtils.writeExtmap = function(headerExtension) {
  1450. return 'a=extmap:' + (headerExtension.id || headerExtension.preferredId) +
  1451. (headerExtension.direction && headerExtension.direction !== 'sendrecv'
  1452. ? '/' + headerExtension.direction
  1453. : '') +
  1454. ' ' + headerExtension.uri + '\r\n';
  1455. };
  1456. // Parses an ftmp line, returns dictionary. Sample input:
  1457. // a=fmtp:96 vbr=on;cng=on
  1458. // Also deals with vbr=on; cng=on
  1459. SDPUtils.parseFmtp = function(line) {
  1460. var parsed = {};
  1461. var kv;
  1462. var parts = line.substr(line.indexOf(' ') + 1).split(';');
  1463. for (var j = 0; j < parts.length; j++) {
  1464. kv = parts[j].trim().split('=');
  1465. parsed[kv[0].trim()] = kv[1];
  1466. }
  1467. return parsed;
  1468. };
  1469. // Generates an a=ftmp line from RTCRtpCodecCapability or RTCRtpCodecParameters.
  1470. SDPUtils.writeFmtp = function(codec) {
  1471. var line = '';
  1472. var pt = codec.payloadType;
  1473. if (codec.preferredPayloadType !== undefined) {
  1474. pt = codec.preferredPayloadType;
  1475. }
  1476. if (codec.parameters && Object.keys(codec.parameters).length) {
  1477. var params = [];
  1478. Object.keys(codec.parameters).forEach(function(param) {
  1479. if (codec.parameters[param]) {
  1480. params.push(param + '=' + codec.parameters[param]);
  1481. } else {
  1482. params.push(param);
  1483. }
  1484. });
  1485. line += 'a=fmtp:' + pt + ' ' + params.join(';') + '\r\n';
  1486. }
  1487. return line;
  1488. };
  1489. // Parses an rtcp-fb line, returns RTCPRtcpFeedback object. Sample input:
  1490. // a=rtcp-fb:98 nack rpsi
  1491. SDPUtils.parseRtcpFb = function(line) {
  1492. var parts = line.substr(line.indexOf(' ') + 1).split(' ');
  1493. return {
  1494. type: parts.shift(),
  1495. parameter: parts.join(' ')
  1496. };
  1497. };
  1498. // Generate a=rtcp-fb lines from RTCRtpCodecCapability or RTCRtpCodecParameters.
  1499. SDPUtils.writeRtcpFb = function(codec) {
  1500. var lines = '';
  1501. var pt = codec.payloadType;
  1502. if (codec.preferredPayloadType !== undefined) {
  1503. pt = codec.preferredPayloadType;
  1504. }
  1505. if (codec.rtcpFeedback && codec.rtcpFeedback.length) {
  1506. // FIXME: special handling for trr-int?
  1507. codec.rtcpFeedback.forEach(function(fb) {
  1508. lines += 'a=rtcp-fb:' + pt + ' ' + fb.type +
  1509. (fb.parameter && fb.parameter.length ? ' ' + fb.parameter : '') +
  1510. '\r\n';
  1511. });
  1512. }
  1513. return lines;
  1514. };
  1515. // Parses an RFC 5576 ssrc media attribute. Sample input:
  1516. // a=ssrc:3735928559 cname:something
  1517. SDPUtils.parseSsrcMedia = function(line) {
  1518. var sp = line.indexOf(' ');
  1519. var parts = {
  1520. ssrc: parseInt(line.substr(7, sp - 7), 10)
  1521. };
  1522. var colon = line.indexOf(':', sp);
  1523. if (colon > -1) {
  1524. parts.attribute = line.substr(sp + 1, colon - sp - 1);
  1525. parts.value = line.substr(colon + 1);
  1526. } else {
  1527. parts.attribute = line.substr(sp + 1);
  1528. }
  1529. return parts;
  1530. };
  1531. SDPUtils.parseSsrcGroup = function(line) {
  1532. var parts = line.substr(13).split(' ');
  1533. return {
  1534. semantics: parts.shift(),
  1535. ssrcs: parts.map(function(ssrc) {
  1536. return parseInt(ssrc, 10);
  1537. })
  1538. };
  1539. };
  1540. // Extracts the MID (RFC 5888) from a media section.
  1541. // returns the MID or undefined if no mid line was found.
  1542. SDPUtils.getMid = function(mediaSection) {
  1543. var mid = SDPUtils.matchPrefix(mediaSection, 'a=mid:')[0];
  1544. if (mid) {
  1545. return mid.substr(6);
  1546. }
  1547. };
  1548. SDPUtils.parseFingerprint = function(line) {
  1549. var parts = line.substr(14).split(' ');
  1550. return {
  1551. algorithm: parts[0].toLowerCase(), // algorithm is case-sensitive in Edge.
  1552. value: parts[1]
  1553. };
  1554. };
  1555. // Extracts DTLS parameters from SDP media section or sessionpart.
  1556. // FIXME: for consistency with other functions this should only
  1557. // get the fingerprint line as input. See also getIceParameters.
  1558. SDPUtils.getDtlsParameters = function(mediaSection, sessionpart) {
  1559. var lines = SDPUtils.matchPrefix(mediaSection + sessionpart,
  1560. 'a=fingerprint:');
  1561. // Note: a=setup line is ignored since we use the 'auto' role.
  1562. // Note2: 'algorithm' is not case sensitive except in Edge.
  1563. return {
  1564. role: 'auto',
  1565. fingerprints: lines.map(SDPUtils.parseFingerprint)
  1566. };
  1567. };
  1568. // Serializes DTLS parameters to SDP.
  1569. SDPUtils.writeDtlsParameters = function(params, setupType) {
  1570. var sdp = 'a=setup:' + setupType + '\r\n';
  1571. params.fingerprints.forEach(function(fp) {
  1572. sdp += 'a=fingerprint:' + fp.algorithm + ' ' + fp.value + '\r\n';
  1573. });
  1574. return sdp;
  1575. };
  1576. // Parses a=crypto lines into
  1577. // https://rawgit.com/aboba/edgertc/master/msortc-rs4.html#dictionary-rtcsrtpsdesparameters-members
  1578. SDPUtils.parseCryptoLine = function(line) {
  1579. var parts = line.substr(9).split(' ');
  1580. return {
  1581. tag: parseInt(parts[0], 10),
  1582. cryptoSuite: parts[1],
  1583. keyParams: parts[2],
  1584. sessionParams: parts.slice(3),
  1585. };
  1586. };
  1587. SDPUtils.writeCryptoLine = function(parameters) {
  1588. return 'a=crypto:' + parameters.tag + ' ' +
  1589. parameters.cryptoSuite + ' ' +
  1590. (typeof parameters.keyParams === 'object'
  1591. ? SDPUtils.writeCryptoKeyParams(parameters.keyParams)
  1592. : parameters.keyParams) +
  1593. (parameters.sessionParams ? ' ' + parameters.sessionParams.join(' ') : '') +
  1594. '\r\n';
  1595. };
  1596. // Parses the crypto key parameters into
  1597. // https://rawgit.com/aboba/edgertc/master/msortc-rs4.html#rtcsrtpkeyparam*
  1598. SDPUtils.parseCryptoKeyParams = function(keyParams) {
  1599. if (keyParams.indexOf('inline:') !== 0) {
  1600. return null;
  1601. }
  1602. var parts = keyParams.substr(7).split('|');
  1603. return {
  1604. keyMethod: 'inline',
  1605. keySalt: parts[0],
  1606. lifeTime: parts[1],
  1607. mkiValue: parts[2] ? parts[2].split(':')[0] : undefined,
  1608. mkiLength: parts[2] ? parts[2].split(':')[1] : undefined,
  1609. };
  1610. };
  1611. SDPUtils.writeCryptoKeyParams = function(keyParams) {
  1612. return keyParams.keyMethod + ':'
  1613. + keyParams.keySalt +
  1614. (keyParams.lifeTime ? '|' + keyParams.lifeTime : '') +
  1615. (keyParams.mkiValue && keyParams.mkiLength
  1616. ? '|' + keyParams.mkiValue + ':' + keyParams.mkiLength
  1617. : '');
  1618. };
  1619. // Extracts all SDES paramters.
  1620. SDPUtils.getCryptoParameters = function(mediaSection, sessionpart) {
  1621. var lines = SDPUtils.matchPrefix(mediaSection + sessionpart,
  1622. 'a=crypto:');
  1623. return lines.map(SDPUtils.parseCryptoLine);
  1624. };
  1625. // Parses ICE information from SDP media section or sessionpart.
  1626. // FIXME: for consistency with other functions this should only
  1627. // get the ice-ufrag and ice-pwd lines as input.
  1628. SDPUtils.getIceParameters = function(mediaSection, sessionpart) {
  1629. var ufrag = SDPUtils.matchPrefix(mediaSection + sessionpart,
  1630. 'a=ice-ufrag:')[0];
  1631. var pwd = SDPUtils.matchPrefix(mediaSection + sessionpart,
  1632. 'a=ice-pwd:')[0];
  1633. if (!(ufrag && pwd)) {
  1634. return null;
  1635. }
  1636. return {
  1637. usernameFragment: ufrag.substr(12),
  1638. password: pwd.substr(10),
  1639. };
  1640. };
  1641. // Serializes ICE parameters to SDP.
  1642. SDPUtils.writeIceParameters = function(params) {
  1643. return 'a=ice-ufrag:' + params.usernameFragment + '\r\n' +
  1644. 'a=ice-pwd:' + params.password + '\r\n';
  1645. };
  1646. // Parses the SDP media section and returns RTCRtpParameters.
  1647. SDPUtils.parseRtpParameters = function(mediaSection) {
  1648. var description = {
  1649. codecs: [],
  1650. headerExtensions: [],
  1651. fecMechanisms: [],
  1652. rtcp: []
  1653. };
  1654. var lines = SDPUtils.splitLines(mediaSection);
  1655. var mline = lines[0].split(' ');
  1656. for (var i = 3; i < mline.length; i++) { // find all codecs from mline[3..]
  1657. var pt = mline[i];
  1658. var rtpmapline = SDPUtils.matchPrefix(
  1659. mediaSection, 'a=rtpmap:' + pt + ' ')[0];
  1660. if (rtpmapline) {
  1661. var codec = SDPUtils.parseRtpMap(rtpmapline);
  1662. var fmtps = SDPUtils.matchPrefix(
  1663. mediaSection, 'a=fmtp:' + pt + ' ');
  1664. // Only the first a=fmtp:<pt> is considered.
  1665. codec.parameters = fmtps.length ? SDPUtils.parseFmtp(fmtps[0]) : {};
  1666. codec.rtcpFeedback = SDPUtils.matchPrefix(
  1667. mediaSection, 'a=rtcp-fb:' + pt + ' ')
  1668. .map(SDPUtils.parseRtcpFb);
  1669. description.codecs.push(codec);
  1670. // parse FEC mechanisms from rtpmap lines.
  1671. switch (codec.name.toUpperCase()) {
  1672. case 'RED':
  1673. case 'ULPFEC':
  1674. description.fecMechanisms.push(codec.name.toUpperCase());
  1675. break;
  1676. }
  1677. }
  1678. }
  1679. SDPUtils.matchPrefix(mediaSection, 'a=extmap:').forEach(function(line) {
  1680. description.headerExtensions.push(SDPUtils.parseExtmap(line));
  1681. });
  1682. // FIXME: parse rtcp.
  1683. return description;
  1684. };
  1685. // Generates parts of the SDP media section describing the capabilities /
  1686. // parameters.
  1687. SDPUtils.writeRtpDescription = function(kind, caps) {
  1688. var sdp = '';
  1689. // Build the mline.
  1690. sdp += 'm=' + kind + ' ';
  1691. sdp += caps.codecs.length > 0 ? '9' : '0'; // reject if no codecs.
  1692. sdp += ' UDP/TLS/RTP/SAVPF ';
  1693. sdp += caps.codecs.map(function(codec) {
  1694. if (codec.preferredPayloadType !== undefined) {
  1695. return codec.preferredPayloadType;
  1696. }
  1697. return codec.payloadType;
  1698. }).join(' ') + '\r\n';
  1699. sdp += 'c=IN IP4 0.0.0.0\r\n';
  1700. sdp += 'a=rtcp:9 IN IP4 0.0.0.0\r\n';
  1701. // Add a=rtpmap lines for each codec. Also fmtp and rtcp-fb.
  1702. caps.codecs.forEach(function(codec) {
  1703. sdp += SDPUtils.writeRtpMap(codec);
  1704. sdp += SDPUtils.writeFmtp(codec);
  1705. sdp += SDPUtils.writeRtcpFb(codec);
  1706. });
  1707. var maxptime = 0;
  1708. caps.codecs.forEach(function(codec) {
  1709. if (codec.maxptime > maxptime) {
  1710. maxptime = codec.maxptime;
  1711. }
  1712. });
  1713. if (maxptime > 0) {
  1714. sdp += 'a=maxptime:' + maxptime + '\r\n';
  1715. }
  1716. sdp += 'a=rtcp-mux\r\n';
  1717. if (caps.headerExtensions) {
  1718. caps.headerExtensions.forEach(function(extension) {
  1719. sdp += SDPUtils.writeExtmap(extension);
  1720. });
  1721. }
  1722. // FIXME: write fecMechanisms.
  1723. return sdp;
  1724. };
  1725. // Parses the SDP media section and returns an array of
  1726. // RTCRtpEncodingParameters.
  1727. SDPUtils.parseRtpEncodingParameters = function(mediaSection) {
  1728. var encodingParameters = [];
  1729. var description = SDPUtils.parseRtpParameters(mediaSection);
  1730. var hasRed = description.fecMechanisms.indexOf('RED') !== -1;
  1731. var hasUlpfec = description.fecMechanisms.indexOf('ULPFEC') !== -1;
  1732. // filter a=ssrc:... cname:, ignore PlanB-msid
  1733. var ssrcs = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')
  1734. .map(function(line) {
  1735. return SDPUtils.parseSsrcMedia(line);
  1736. })
  1737. .filter(function(parts) {
  1738. return parts.attribute === 'cname';
  1739. });
  1740. var primarySsrc = ssrcs.length > 0 && ssrcs[0].ssrc;
  1741. var secondarySsrc;
  1742. var flows = SDPUtils.matchPrefix(mediaSection, 'a=ssrc-group:FID')
  1743. .map(function(line) {
  1744. var parts = line.substr(17).split(' ');
  1745. return parts.map(function(part) {
  1746. return parseInt(part, 10);
  1747. });
  1748. });
  1749. if (flows.length > 0 && flows[0].length > 1 && flows[0][0] === primarySsrc) {
  1750. secondarySsrc = flows[0][1];
  1751. }
  1752. description.codecs.forEach(function(codec) {
  1753. if (codec.name.toUpperCase() === 'RTX' && codec.parameters.apt) {
  1754. var encParam = {
  1755. ssrc: primarySsrc,
  1756. codecPayloadType: parseInt(codec.parameters.apt, 10)
  1757. };
  1758. if (primarySsrc && secondarySsrc) {
  1759. encParam.rtx = {ssrc: secondarySsrc};
  1760. }
  1761. encodingParameters.push(encParam);
  1762. if (hasRed) {
  1763. encParam = JSON.parse(JSON.stringify(encParam));
  1764. encParam.fec = {
  1765. ssrc: primarySsrc,
  1766. mechanism: hasUlpfec ? 'red+ulpfec' : 'red'
  1767. };
  1768. encodingParameters.push(encParam);
  1769. }
  1770. }
  1771. });
  1772. if (encodingParameters.length === 0 && primarySsrc) {
  1773. encodingParameters.push({
  1774. ssrc: primarySsrc
  1775. });
  1776. }
  1777. // we support both b=AS and b=TIAS but interpret AS as TIAS.
  1778. var bandwidth = SDPUtils.matchPrefix(mediaSection, 'b=');
  1779. if (bandwidth.length) {
  1780. if (bandwidth[0].indexOf('b=TIAS:') === 0) {
  1781. bandwidth = parseInt(bandwidth[0].substr(7), 10);
  1782. } else if (bandwidth[0].indexOf('b=AS:') === 0) {
  1783. // use formula from JSEP to convert b=AS to TIAS value.
  1784. bandwidth = parseInt(bandwidth[0].substr(5), 10) * 1000 * 0.95
  1785. - (50 * 40 * 8);
  1786. } else {
  1787. bandwidth = undefined;
  1788. }
  1789. encodingParameters.forEach(function(params) {
  1790. params.maxBitrate = bandwidth;
  1791. });
  1792. }
  1793. return encodingParameters;
  1794. };
  1795. // parses http://draft.ortc.org/#rtcrtcpparameters*
  1796. SDPUtils.parseRtcpParameters = function(mediaSection) {
  1797. var rtcpParameters = {};
  1798. // Gets the first SSRC. Note tha with RTX there might be multiple
  1799. // SSRCs.
  1800. var remoteSsrc = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')
  1801. .map(function(line) {
  1802. return SDPUtils.parseSsrcMedia(line);
  1803. })
  1804. .filter(function(obj) {
  1805. return obj.attribute === 'cname';
  1806. })[0];
  1807. if (remoteSsrc) {
  1808. rtcpParameters.cname = remoteSsrc.value;
  1809. rtcpParameters.ssrc = remoteSsrc.ssrc;
  1810. }
  1811. // Edge uses the compound attribute instead of reducedSize
  1812. // compound is !reducedSize
  1813. var rsize = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-rsize');
  1814. rtcpParameters.reducedSize = rsize.length > 0;
  1815. rtcpParameters.compound = rsize.length === 0;
  1816. // parses the rtcp-mux attrіbute.
  1817. // Note that Edge does not support unmuxed RTCP.
  1818. var mux = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-mux');
  1819. rtcpParameters.mux = mux.length > 0;
  1820. return rtcpParameters;
  1821. };
  1822. // parses either a=msid: or a=ssrc:... msid lines and returns
  1823. // the id of the MediaStream and MediaStreamTrack.
  1824. SDPUtils.parseMsid = function(mediaSection) {
  1825. var parts;
  1826. var spec = SDPUtils.matchPrefix(mediaSection, 'a=msid:');
  1827. if (spec.length === 1) {
  1828. parts = spec[0].substr(7).split(' ');
  1829. return {stream: parts[0], track: parts[1]};
  1830. }
  1831. var planB = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:')
  1832. .map(function(line) {
  1833. return SDPUtils.parseSsrcMedia(line);
  1834. })
  1835. .filter(function(msidParts) {
  1836. return msidParts.attribute === 'msid';
  1837. });
  1838. if (planB.length > 0) {
  1839. parts = planB[0].value.split(' ');
  1840. return {stream: parts[0], track: parts[1]};
  1841. }
  1842. };
  1843. // SCTP
  1844. // parses draft-ietf-mmusic-sctp-sdp-26 first and falls back
  1845. // to draft-ietf-mmusic-sctp-sdp-05
  1846. SDPUtils.parseSctpDescription = function(mediaSection) {
  1847. var mline = SDPUtils.parseMLine(mediaSection);
  1848. var maxSizeLine = SDPUtils.matchPrefix(mediaSection, 'a=max-message-size:');
  1849. var maxMessageSize;
  1850. if (maxSizeLine.length > 0) {
  1851. maxMessageSize = parseInt(maxSizeLine[0].substr(19), 10);
  1852. }
  1853. if (isNaN(maxMessageSize)) {
  1854. maxMessageSize = 65536;
  1855. }
  1856. var sctpPort = SDPUtils.matchPrefix(mediaSection, 'a=sctp-port:');
  1857. if (sctpPort.length > 0) {
  1858. return {
  1859. port: parseInt(sctpPort[0].substr(12), 10),
  1860. protocol: mline.fmt,
  1861. maxMessageSize: maxMessageSize
  1862. };
  1863. }
  1864. var sctpMapLines = SDPUtils.matchPrefix(mediaSection, 'a=sctpmap:');
  1865. if (sctpMapLines.length > 0) {
  1866. var parts = SDPUtils.matchPrefix(mediaSection, 'a=sctpmap:')[0]
  1867. .substr(10)
  1868. .split(' ');
  1869. return {
  1870. port: parseInt(parts[0], 10),
  1871. protocol: parts[1],
  1872. maxMessageSize: maxMessageSize
  1873. };
  1874. }
  1875. };
  1876. // SCTP
  1877. // outputs the draft-ietf-mmusic-sctp-sdp-26 version that all browsers
  1878. // support by now receiving in this format, unless we originally parsed
  1879. // as the draft-ietf-mmusic-sctp-sdp-05 format (indicated by the m-line
  1880. // protocol of DTLS/SCTP -- without UDP/ or TCP/)
  1881. SDPUtils.writeSctpDescription = function(media, sctp) {
  1882. var output = [];
  1883. if (media.protocol !== 'DTLS/SCTP') {
  1884. output = [
  1885. 'm=' + media.kind + ' 9 ' + media.protocol + ' ' + sctp.protocol + '\r\n',
  1886. 'c=IN IP4 0.0.0.0\r\n',
  1887. 'a=sctp-port:' + sctp.port + '\r\n'
  1888. ];
  1889. } else {
  1890. output = [
  1891. 'm=' + media.kind + ' 9 ' + media.protocol + ' ' + sctp.port + '\r\n',
  1892. 'c=IN IP4 0.0.0.0\r\n',
  1893. 'a=sctpmap:' + sctp.port + ' ' + sctp.protocol + ' 65535\r\n'
  1894. ];
  1895. }
  1896. if (sctp.maxMessageSize !== undefined) {
  1897. output.push('a=max-message-size:' + sctp.maxMessageSize + '\r\n');
  1898. }
  1899. return output.join('');
  1900. };
  1901. // Generate a session ID for SDP.
  1902. // https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-20#section-5.2.1
  1903. // recommends using a cryptographically random +ve 64-bit value
  1904. // but right now this should be acceptable and within the right range
  1905. SDPUtils.generateSessionId = function() {
  1906. return Math.random().toString().substr(2, 21);
  1907. };
  1908. // Write boilder plate for start of SDP
  1909. // sessId argument is optional - if not supplied it will
  1910. // be generated randomly
  1911. // sessVersion is optional and defaults to 2
  1912. // sessUser is optional and defaults to 'thisisadapterortc'
  1913. SDPUtils.writeSessionBoilerplate = function(sessId, sessVer, sessUser) {
  1914. var sessionId;
  1915. var version = sessVer !== undefined ? sessVer : 2;
  1916. if (sessId) {
  1917. sessionId = sessId;
  1918. } else {
  1919. sessionId = SDPUtils.generateSessionId();
  1920. }
  1921. var user = sessUser || 'thisisadapterortc';
  1922. // FIXME: sess-id should be an NTP timestamp.
  1923. return 'v=0\r\n' +
  1924. 'o=' + user + ' ' + sessionId + ' ' + version +
  1925. ' IN IP4 127.0.0.1\r\n' +
  1926. 's=-\r\n' +
  1927. 't=0 0\r\n';
  1928. };
  1929. SDPUtils.writeMediaSection = function(transceiver, caps, type, stream) {
  1930. var sdp = SDPUtils.writeRtpDescription(transceiver.kind, caps);
  1931. // Map ICE parameters (ufrag, pwd) to SDP.
  1932. sdp += SDPUtils.writeIceParameters(
  1933. transceiver.iceGatherer.getLocalParameters());
  1934. // Map DTLS parameters to SDP.
  1935. sdp += SDPUtils.writeDtlsParameters(
  1936. transceiver.dtlsTransport.getLocalParameters(),
  1937. type === 'offer' ? 'actpass' : 'active');
  1938. sdp += 'a=mid:' + transceiver.mid + '\r\n';
  1939. if (transceiver.direction) {
  1940. sdp += 'a=' + transceiver.direction + '\r\n';
  1941. } else if (transceiver.rtpSender && transceiver.rtpReceiver) {
  1942. sdp += 'a=sendrecv\r\n';
  1943. } else if (transceiver.rtpSender) {
  1944. sdp += 'a=sendonly\r\n';
  1945. } else if (transceiver.rtpReceiver) {
  1946. sdp += 'a=recvonly\r\n';
  1947. } else {
  1948. sdp += 'a=inactive\r\n';
  1949. }
  1950. if (transceiver.rtpSender) {
  1951. // spec.
  1952. var msid = 'msid:' + stream.id + ' ' +
  1953. transceiver.rtpSender.track.id + '\r\n';
  1954. sdp += 'a=' + msid;
  1955. // for Chrome.
  1956. sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc +
  1957. ' ' + msid;
  1958. if (transceiver.sendEncodingParameters[0].rtx) {
  1959. sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc +
  1960. ' ' + msid;
  1961. sdp += 'a=ssrc-group:FID ' +
  1962. transceiver.sendEncodingParameters[0].ssrc + ' ' +
  1963. transceiver.sendEncodingParameters[0].rtx.ssrc +
  1964. '\r\n';
  1965. }
  1966. }
  1967. // FIXME: this should be written by writeRtpDescription.
  1968. sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc +
  1969. ' cname:' + SDPUtils.localCName + '\r\n';
  1970. if (transceiver.rtpSender && transceiver.sendEncodingParameters[0].rtx) {
  1971. sdp += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc +
  1972. ' cname:' + SDPUtils.localCName + '\r\n';
  1973. }
  1974. return sdp;
  1975. };
  1976. // Gets the direction from the mediaSection or the sessionpart.
  1977. SDPUtils.getDirection = function(mediaSection, sessionpart) {
  1978. // Look for sendrecv, sendonly, recvonly, inactive, default to sendrecv.
  1979. var lines = SDPUtils.splitLines(mediaSection);
  1980. for (var i = 0; i < lines.length; i++) {
  1981. switch (lines[i]) {
  1982. case 'a=sendrecv':
  1983. case 'a=sendonly':
  1984. case 'a=recvonly':
  1985. case 'a=inactive':
  1986. return lines[i].substr(2);
  1987. // FIXME: What should happen here?
  1988. }
  1989. }
  1990. if (sessionpart) {
  1991. return SDPUtils.getDirection(sessionpart);
  1992. }
  1993. return 'sendrecv';
  1994. };
  1995. SDPUtils.getKind = function(mediaSection) {
  1996. var lines = SDPUtils.splitLines(mediaSection);
  1997. var mline = lines[0].split(' ');
  1998. return mline[0].substr(2);
  1999. };
  2000. SDPUtils.isRejected = function(mediaSection) {
  2001. return mediaSection.split(' ', 2)[1] === '0';
  2002. };
  2003. SDPUtils.parseMLine = function(mediaSection) {
  2004. var lines = SDPUtils.splitLines(mediaSection);
  2005. var parts = lines[0].substr(2).split(' ');
  2006. return {
  2007. kind: parts[0],
  2008. port: parseInt(parts[1], 10),
  2009. protocol: parts[2],
  2010. fmt: parts.slice(3).join(' ')
  2011. };
  2012. };
  2013. SDPUtils.parseOLine = function(mediaSection) {
  2014. var line = SDPUtils.matchPrefix(mediaSection, 'o=')[0];
  2015. var parts = line.substr(2).split(' ');
  2016. return {
  2017. username: parts[0],
  2018. sessionId: parts[1],
  2019. sessionVersion: parseInt(parts[2], 10),
  2020. netType: parts[3],
  2021. addressType: parts[4],
  2022. address: parts[5]
  2023. };
  2024. };
  2025. // a very naive interpretation of a valid SDP.
  2026. SDPUtils.isValidSDP = function(blob) {
  2027. if (typeof blob !== 'string' || blob.length === 0) {
  2028. return false;
  2029. }
  2030. var lines = SDPUtils.splitLines(blob);
  2031. for (var i = 0; i < lines.length; i++) {
  2032. if (lines[i].length < 2 || lines[i].charAt(1) !== '=') {
  2033. return false;
  2034. }
  2035. // TODO: check the modifier a bit more.
  2036. }
  2037. return true;
  2038. };
  2039. // Expose public methods.
  2040. {
  2041. module.exports = SDPUtils;
  2042. }
  2043. });
  2044. /*
  2045. * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
  2046. *
  2047. * Use of this source code is governed by a BSD-style license
  2048. * that can be found in the LICENSE file in the root of the source
  2049. * tree.
  2050. */
  2051. function fixStatsType(stat) {
  2052. return {
  2053. inboundrtp: 'inbound-rtp',
  2054. outboundrtp: 'outbound-rtp',
  2055. candidatepair: 'candidate-pair',
  2056. localcandidate: 'local-candidate',
  2057. remotecandidate: 'remote-candidate'
  2058. }[stat.type] || stat.type;
  2059. }
  2060. function writeMediaSection(transceiver, caps, type, stream, dtlsRole) {
  2061. var sdp$1 = sdp.writeRtpDescription(transceiver.kind, caps);
  2062. // Map ICE parameters (ufrag, pwd) to SDP.
  2063. sdp$1 += sdp.writeIceParameters(
  2064. transceiver.iceGatherer.getLocalParameters());
  2065. // Map DTLS parameters to SDP.
  2066. sdp$1 += sdp.writeDtlsParameters(
  2067. transceiver.dtlsTransport.getLocalParameters(),
  2068. type === 'offer' ? 'actpass' : dtlsRole || 'active');
  2069. sdp$1 += 'a=mid:' + transceiver.mid + '\r\n';
  2070. if (transceiver.rtpSender && transceiver.rtpReceiver) {
  2071. sdp$1 += 'a=sendrecv\r\n';
  2072. } else if (transceiver.rtpSender) {
  2073. sdp$1 += 'a=sendonly\r\n';
  2074. } else if (transceiver.rtpReceiver) {
  2075. sdp$1 += 'a=recvonly\r\n';
  2076. } else {
  2077. sdp$1 += 'a=inactive\r\n';
  2078. }
  2079. if (transceiver.rtpSender) {
  2080. var trackId = transceiver.rtpSender._initialTrackId ||
  2081. transceiver.rtpSender.track.id;
  2082. transceiver.rtpSender._initialTrackId = trackId;
  2083. // spec.
  2084. var msid = 'msid:' + (stream ? stream.id : '-') + ' ' +
  2085. trackId + '\r\n';
  2086. sdp$1 += 'a=' + msid;
  2087. // for Chrome. Legacy should no longer be required.
  2088. sdp$1 += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc +
  2089. ' ' + msid;
  2090. // RTX
  2091. if (transceiver.sendEncodingParameters[0].rtx) {
  2092. sdp$1 += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc +
  2093. ' ' + msid;
  2094. sdp$1 += 'a=ssrc-group:FID ' +
  2095. transceiver.sendEncodingParameters[0].ssrc + ' ' +
  2096. transceiver.sendEncodingParameters[0].rtx.ssrc +
  2097. '\r\n';
  2098. }
  2099. }
  2100. // FIXME: this should be written by writeRtpDescription.
  2101. sdp$1 += 'a=ssrc:' + transceiver.sendEncodingParameters[0].ssrc +
  2102. ' cname:' + sdp.localCName + '\r\n';
  2103. if (transceiver.rtpSender && transceiver.sendEncodingParameters[0].rtx) {
  2104. sdp$1 += 'a=ssrc:' + transceiver.sendEncodingParameters[0].rtx.ssrc +
  2105. ' cname:' + sdp.localCName + '\r\n';
  2106. }
  2107. return sdp$1;
  2108. }
  2109. // Edge does not like
  2110. // 1) stun: filtered after 14393 unless ?transport=udp is present
  2111. // 2) turn: that does not have all of turn:host:port?transport=udp
  2112. // 3) turn: with ipv6 addresses
  2113. // 4) turn: occurring muliple times
  2114. function filterIceServers(iceServers, edgeVersion) {
  2115. var hasTurn = false;
  2116. iceServers = JSON.parse(JSON.stringify(iceServers));
  2117. return iceServers.filter(function(server) {
  2118. if (server && (server.urls || server.url)) {
  2119. var urls = server.urls || server.url;
  2120. if (server.url && !server.urls) {
  2121. console.warn('RTCIceServer.url is deprecated! Use urls instead.');
  2122. }
  2123. var isString = typeof urls === 'string';
  2124. if (isString) {
  2125. urls = [urls];
  2126. }
  2127. urls = urls.filter(function(url) {
  2128. var validTurn = url.indexOf('turn:') === 0 &&
  2129. url.indexOf('transport=udp') !== -1 &&
  2130. url.indexOf('turn:[') === -1 &&
  2131. !hasTurn;
  2132. if (validTurn) {
  2133. hasTurn = true;
  2134. return true;
  2135. }
  2136. return url.indexOf('stun:') === 0 && edgeVersion >= 14393 &&
  2137. url.indexOf('?transport=udp') === -1;
  2138. });
  2139. delete server.url;
  2140. server.urls = isString ? urls[0] : urls;
  2141. return !!urls.length;
  2142. }
  2143. });
  2144. }
  2145. // Determines the intersection of local and remote capabilities.
  2146. function getCommonCapabilities(localCapabilities, remoteCapabilities) {
  2147. var commonCapabilities = {
  2148. codecs: [],
  2149. headerExtensions: [],
  2150. fecMechanisms: []
  2151. };
  2152. var findCodecByPayloadType = function(pt, codecs) {
  2153. pt = parseInt(pt, 10);
  2154. for (var i = 0; i < codecs.length; i++) {
  2155. if (codecs[i].payloadType === pt ||
  2156. codecs[i].preferredPayloadType === pt) {
  2157. return codecs[i];
  2158. }
  2159. }
  2160. };
  2161. var rtxCapabilityMatches = function(lRtx, rRtx, lCodecs, rCodecs) {
  2162. var lCodec = findCodecByPayloadType(lRtx.parameters.apt, lCodecs);
  2163. var rCodec = findCodecByPayloadType(rRtx.parameters.apt, rCodecs);
  2164. return lCodec && rCodec &&
  2165. lCodec.name.toLowerCase() === rCodec.name.toLowerCase();
  2166. };
  2167. localCapabilities.codecs.forEach(function(lCodec) {
  2168. for (var i = 0; i < remoteCapabilities.codecs.length; i++) {
  2169. var rCodec = remoteCapabilities.codecs[i];
  2170. if (lCodec.name.toLowerCase() === rCodec.name.toLowerCase() &&
  2171. lCodec.clockRate === rCodec.clockRate) {
  2172. if (lCodec.name.toLowerCase() === 'rtx' &&
  2173. lCodec.parameters && rCodec.parameters.apt) {
  2174. // for RTX we need to find the local rtx that has a apt
  2175. // which points to the same local codec as the remote one.
  2176. if (!rtxCapabilityMatches(lCodec, rCodec,
  2177. localCapabilities.codecs, remoteCapabilities.codecs)) {
  2178. continue;
  2179. }
  2180. }
  2181. rCodec = JSON.parse(JSON.stringify(rCodec)); // deepcopy
  2182. // number of channels is the highest common number of channels
  2183. rCodec.numChannels = Math.min(lCodec.numChannels,
  2184. rCodec.numChannels);
  2185. // push rCodec so we reply with offerer payload type
  2186. commonCapabilities.codecs.push(rCodec);
  2187. // determine common feedback mechanisms
  2188. rCodec.rtcpFeedback = rCodec.rtcpFeedback.filter(function(fb) {
  2189. for (var j = 0; j < lCodec.rtcpFeedback.length; j++) {
  2190. if (lCodec.rtcpFeedback[j].type === fb.type &&
  2191. lCodec.rtcpFeedback[j].parameter === fb.parameter) {
  2192. return true;
  2193. }
  2194. }
  2195. return false;
  2196. });
  2197. // FIXME: also need to determine .parameters
  2198. // see https://github.com/openpeer/ortc/issues/569
  2199. break;
  2200. }
  2201. }
  2202. });
  2203. localCapabilities.headerExtensions.forEach(function(lHeaderExtension) {
  2204. for (var i = 0; i < remoteCapabilities.headerExtensions.length;
  2205. i++) {
  2206. var rHeaderExtension = remoteCapabilities.headerExtensions[i];
  2207. if (lHeaderExtension.uri === rHeaderExtension.uri) {
  2208. commonCapabilities.headerExtensions.push(rHeaderExtension);
  2209. break;
  2210. }
  2211. }
  2212. });
  2213. // FIXME: fecMechanisms
  2214. return commonCapabilities;
  2215. }
  2216. // is action=setLocalDescription with type allowed in signalingState
  2217. function isActionAllowedInSignalingState(action, type, signalingState) {
  2218. return {
  2219. offer: {
  2220. setLocalDescription: ['stable', 'have-local-offer'],
  2221. setRemoteDescription: ['stable', 'have-remote-offer']
  2222. },
  2223. answer: {
  2224. setLocalDescription: ['have-remote-offer', 'have-local-pranswer'],
  2225. setRemoteDescription: ['have-local-offer', 'have-remote-pranswer']
  2226. }
  2227. }[type][action].indexOf(signalingState) !== -1;
  2228. }
  2229. function maybeAddCandidate(iceTransport, candidate) {
  2230. // Edge's internal representation adds some fields therefore
  2231. // not all fieldѕ are taken into account.
  2232. var alreadyAdded = iceTransport.getRemoteCandidates()
  2233. .find(function(remoteCandidate) {
  2234. return candidate.foundation === remoteCandidate.foundation &&
  2235. candidate.ip === remoteCandidate.ip &&
  2236. candidate.port === remoteCandidate.port &&
  2237. candidate.priority === remoteCandidate.priority &&
  2238. candidate.protocol === remoteCandidate.protocol &&
  2239. candidate.type === remoteCandidate.type;
  2240. });
  2241. if (!alreadyAdded) {
  2242. iceTransport.addRemoteCandidate(candidate);
  2243. }
  2244. return !alreadyAdded;
  2245. }
  2246. function makeError(name, description) {
  2247. var e = new Error(description);
  2248. e.name = name;
  2249. // legacy error codes from https://heycam.github.io/webidl/#idl-DOMException-error-names
  2250. e.code = {
  2251. NotSupportedError: 9,
  2252. InvalidStateError: 11,
  2253. InvalidAccessError: 15,
  2254. TypeError: undefined,
  2255. OperationError: undefined
  2256. }[name];
  2257. return e;
  2258. }
  2259. var rtcpeerconnection = function(window, edgeVersion) {
  2260. // https://w3c.github.io/mediacapture-main/#mediastream
  2261. // Helper function to add the track to the stream and
  2262. // dispatch the event ourselves.
  2263. function addTrackToStreamAndFireEvent(track, stream) {
  2264. stream.addTrack(track);
  2265. stream.dispatchEvent(new window.MediaStreamTrackEvent('addtrack',
  2266. {track: track}));
  2267. }
  2268. function removeTrackFromStreamAndFireEvent(track, stream) {
  2269. stream.removeTrack(track);
  2270. stream.dispatchEvent(new window.MediaStreamTrackEvent('removetrack',
  2271. {track: track}));
  2272. }
  2273. function fireAddTrack(pc, track, receiver, streams) {
  2274. var trackEvent = new Event('track');
  2275. trackEvent.track = track;
  2276. trackEvent.receiver = receiver;
  2277. trackEvent.transceiver = {receiver: receiver};
  2278. trackEvent.streams = streams;
  2279. window.setTimeout(function() {
  2280. pc._dispatchEvent('track', trackEvent);
  2281. });
  2282. }
  2283. var RTCPeerConnection = function(config) {
  2284. var pc = this;
  2285. var _eventTarget = document.createDocumentFragment();
  2286. ['addEventListener', 'removeEventListener', 'dispatchEvent']
  2287. .forEach(function(method) {
  2288. pc[method] = _eventTarget[method].bind(_eventTarget);
  2289. });
  2290. this.canTrickleIceCandidates = null;
  2291. this.needNegotiation = false;
  2292. this.localStreams = [];
  2293. this.remoteStreams = [];
  2294. this._localDescription = null;
  2295. this._remoteDescription = null;
  2296. this.signalingState = 'stable';
  2297. this.iceConnectionState = 'new';
  2298. this.connectionState = 'new';
  2299. this.iceGatheringState = 'new';
  2300. config = JSON.parse(JSON.stringify(config || {}));
  2301. this.usingBundle = config.bundlePolicy === 'max-bundle';
  2302. if (config.rtcpMuxPolicy === 'negotiate') {
  2303. throw(makeError('NotSupportedError',
  2304. 'rtcpMuxPolicy \'negotiate\' is not supported'));
  2305. } else if (!config.rtcpMuxPolicy) {
  2306. config.rtcpMuxPolicy = 'require';
  2307. }
  2308. switch (config.iceTransportPolicy) {
  2309. case 'all':
  2310. case 'relay':
  2311. break;
  2312. default:
  2313. config.iceTransportPolicy = 'all';
  2314. break;
  2315. }
  2316. switch (config.bundlePolicy) {
  2317. case 'balanced':
  2318. case 'max-compat':
  2319. case 'max-bundle':
  2320. break;
  2321. default:
  2322. config.bundlePolicy = 'balanced';
  2323. break;
  2324. }
  2325. config.iceServers = filterIceServers(config.iceServers || [], edgeVersion);
  2326. this._iceGatherers = [];
  2327. if (config.iceCandidatePoolSize) {
  2328. for (var i = config.iceCandidatePoolSize; i > 0; i--) {
  2329. this._iceGatherers.push(new window.RTCIceGatherer({
  2330. iceServers: config.iceServers,
  2331. gatherPolicy: config.iceTransportPolicy
  2332. }));
  2333. }
  2334. } else {
  2335. config.iceCandidatePoolSize = 0;
  2336. }
  2337. this._config = config;
  2338. // per-track iceGathers, iceTransports, dtlsTransports, rtpSenders, ...
  2339. // everything that is needed to describe a SDP m-line.
  2340. this.transceivers = [];
  2341. this._sdpSessionId = sdp.generateSessionId();
  2342. this._sdpSessionVersion = 0;
  2343. this._dtlsRole = undefined; // role for a=setup to use in answers.
  2344. this._isClosed = false;
  2345. };
  2346. Object.defineProperty(RTCPeerConnection.prototype, 'localDescription', {
  2347. configurable: true,
  2348. get: function() {
  2349. return this._localDescription;
  2350. }
  2351. });
  2352. Object.defineProperty(RTCPeerConnection.prototype, 'remoteDescription', {
  2353. configurable: true,
  2354. get: function() {
  2355. return this._remoteDescription;
  2356. }
  2357. });
  2358. // set up event handlers on prototype
  2359. RTCPeerConnection.prototype.onicecandidate = null;
  2360. RTCPeerConnection.prototype.onaddstream = null;
  2361. RTCPeerConnection.prototype.ontrack = null;
  2362. RTCPeerConnection.prototype.onremovestream = null;
  2363. RTCPeerConnection.prototype.onsignalingstatechange = null;
  2364. RTCPeerConnection.prototype.oniceconnectionstatechange = null;
  2365. RTCPeerConnection.prototype.onconnectionstatechange = null;
  2366. RTCPeerConnection.prototype.onicegatheringstatechange = null;
  2367. RTCPeerConnection.prototype.onnegotiationneeded = null;
  2368. RTCPeerConnection.prototype.ondatachannel = null;
  2369. RTCPeerConnection.prototype._dispatchEvent = function(name, event) {
  2370. if (this._isClosed) {
  2371. return;
  2372. }
  2373. this.dispatchEvent(event);
  2374. if (typeof this['on' + name] === 'function') {
  2375. this['on' + name](event);
  2376. }
  2377. };
  2378. RTCPeerConnection.prototype._emitGatheringStateChange = function() {
  2379. var event = new Event('icegatheringstatechange');
  2380. this._dispatchEvent('icegatheringstatechange', event);
  2381. };
  2382. RTCPeerConnection.prototype.getConfiguration = function() {
  2383. return this._config;
  2384. };
  2385. RTCPeerConnection.prototype.getLocalStreams = function() {
  2386. return this.localStreams;
  2387. };
  2388. RTCPeerConnection.prototype.getRemoteStreams = function() {
  2389. return this.remoteStreams;
  2390. };
  2391. // internal helper to create a transceiver object.
  2392. // (which is not yet the same as the WebRTC 1.0 transceiver)
  2393. RTCPeerConnection.prototype._createTransceiver = function(kind, doNotAdd) {
  2394. var hasBundleTransport = this.transceivers.length > 0;
  2395. var transceiver = {
  2396. track: null,
  2397. iceGatherer: null,
  2398. iceTransport: null,
  2399. dtlsTransport: null,
  2400. localCapabilities: null,
  2401. remoteCapabilities: null,
  2402. rtpSender: null,
  2403. rtpReceiver: null,
  2404. kind: kind,
  2405. mid: null,
  2406. sendEncodingParameters: null,
  2407. recvEncodingParameters: null,
  2408. stream: null,
  2409. associatedRemoteMediaStreams: [],
  2410. wantReceive: true
  2411. };
  2412. if (this.usingBundle && hasBundleTransport) {
  2413. transceiver.iceTransport = this.transceivers[0].iceTransport;
  2414. transceiver.dtlsTransport = this.transceivers[0].dtlsTransport;
  2415. } else {
  2416. var transports = this._createIceAndDtlsTransports();
  2417. transceiver.iceTransport = transports.iceTransport;
  2418. transceiver.dtlsTransport = transports.dtlsTransport;
  2419. }
  2420. if (!doNotAdd) {
  2421. this.transceivers.push(transceiver);
  2422. }
  2423. return transceiver;
  2424. };
  2425. RTCPeerConnection.prototype.addTrack = function(track, stream) {
  2426. if (this._isClosed) {
  2427. throw makeError('InvalidStateError',
  2428. 'Attempted to call addTrack on a closed peerconnection.');
  2429. }
  2430. var alreadyExists = this.transceivers.find(function(s) {
  2431. return s.track === track;
  2432. });
  2433. if (alreadyExists) {
  2434. throw makeError('InvalidAccessError', 'Track already exists.');
  2435. }
  2436. var transceiver;
  2437. for (var i = 0; i < this.transceivers.length; i++) {
  2438. if (!this.transceivers[i].track &&
  2439. this.transceivers[i].kind === track.kind) {
  2440. transceiver = this.transceivers[i];
  2441. }
  2442. }
  2443. if (!transceiver) {
  2444. transceiver = this._createTransceiver(track.kind);
  2445. }
  2446. this._maybeFireNegotiationNeeded();
  2447. if (this.localStreams.indexOf(stream) === -1) {
  2448. this.localStreams.push(stream);
  2449. }
  2450. transceiver.track = track;
  2451. transceiver.stream = stream;
  2452. transceiver.rtpSender = new window.RTCRtpSender(track,
  2453. transceiver.dtlsTransport);
  2454. return transceiver.rtpSender;
  2455. };
  2456. RTCPeerConnection.prototype.addStream = function(stream) {
  2457. var pc = this;
  2458. if (edgeVersion >= 15025) {
  2459. stream.getTracks().forEach(function(track) {
  2460. pc.addTrack(track, stream);
  2461. });
  2462. } else {
  2463. // Clone is necessary for local demos mostly, attaching directly
  2464. // to two different senders does not work (build 10547).
  2465. // Fixed in 15025 (or earlier)
  2466. var clonedStream = stream.clone();
  2467. stream.getTracks().forEach(function(track, idx) {
  2468. var clonedTrack = clonedStream.getTracks()[idx];
  2469. track.addEventListener('enabled', function(event) {
  2470. clonedTrack.enabled = event.enabled;
  2471. });
  2472. });
  2473. clonedStream.getTracks().forEach(function(track) {
  2474. pc.addTrack(track, clonedStream);
  2475. });
  2476. }
  2477. };
  2478. RTCPeerConnection.prototype.removeTrack = function(sender) {
  2479. if (this._isClosed) {
  2480. throw makeError('InvalidStateError',
  2481. 'Attempted to call removeTrack on a closed peerconnection.');
  2482. }
  2483. if (!(sender instanceof window.RTCRtpSender)) {
  2484. throw new TypeError('Argument 1 of RTCPeerConnection.removeTrack ' +
  2485. 'does not implement interface RTCRtpSender.');
  2486. }
  2487. var transceiver = this.transceivers.find(function(t) {
  2488. return t.rtpSender === sender;
  2489. });
  2490. if (!transceiver) {
  2491. throw makeError('InvalidAccessError',
  2492. 'Sender was not created by this connection.');
  2493. }
  2494. var stream = transceiver.stream;
  2495. transceiver.rtpSender.stop();
  2496. transceiver.rtpSender = null;
  2497. transceiver.track = null;
  2498. transceiver.stream = null;
  2499. // remove the stream from the set of local streams
  2500. var localStreams = this.transceivers.map(function(t) {
  2501. return t.stream;
  2502. });
  2503. if (localStreams.indexOf(stream) === -1 &&
  2504. this.localStreams.indexOf(stream) > -1) {
  2505. this.localStreams.splice(this.localStreams.indexOf(stream), 1);
  2506. }
  2507. this._maybeFireNegotiationNeeded();
  2508. };
  2509. RTCPeerConnection.prototype.removeStream = function(stream) {
  2510. var pc = this;
  2511. stream.getTracks().forEach(function(track) {
  2512. var sender = pc.getSenders().find(function(s) {
  2513. return s.track === track;
  2514. });
  2515. if (sender) {
  2516. pc.removeTrack(sender);
  2517. }
  2518. });
  2519. };
  2520. RTCPeerConnection.prototype.getSenders = function() {
  2521. return this.transceivers.filter(function(transceiver) {
  2522. return !!transceiver.rtpSender;
  2523. })
  2524. .map(function(transceiver) {
  2525. return transceiver.rtpSender;
  2526. });
  2527. };
  2528. RTCPeerConnection.prototype.getReceivers = function() {
  2529. return this.transceivers.filter(function(transceiver) {
  2530. return !!transceiver.rtpReceiver;
  2531. })
  2532. .map(function(transceiver) {
  2533. return transceiver.rtpReceiver;
  2534. });
  2535. };
  2536. RTCPeerConnection.prototype._createIceGatherer = function(sdpMLineIndex,
  2537. usingBundle) {
  2538. var pc = this;
  2539. if (usingBundle && sdpMLineIndex > 0) {
  2540. return this.transceivers[0].iceGatherer;
  2541. } else if (this._iceGatherers.length) {
  2542. return this._iceGatherers.shift();
  2543. }
  2544. var iceGatherer = new window.RTCIceGatherer({
  2545. iceServers: this._config.iceServers,
  2546. gatherPolicy: this._config.iceTransportPolicy
  2547. });
  2548. Object.defineProperty(iceGatherer, 'state',
  2549. {value: 'new', writable: true}
  2550. );
  2551. this.transceivers[sdpMLineIndex].bufferedCandidateEvents = [];
  2552. this.transceivers[sdpMLineIndex].bufferCandidates = function(event) {
  2553. var end = !event.candidate || Object.keys(event.candidate).length === 0;
  2554. // polyfill since RTCIceGatherer.state is not implemented in
  2555. // Edge 10547 yet.
  2556. iceGatherer.state = end ? 'completed' : 'gathering';
  2557. if (pc.transceivers[sdpMLineIndex].bufferedCandidateEvents !== null) {
  2558. pc.transceivers[sdpMLineIndex].bufferedCandidateEvents.push(event);
  2559. }
  2560. };
  2561. iceGatherer.addEventListener('localcandidate',
  2562. this.transceivers[sdpMLineIndex].bufferCandidates);
  2563. return iceGatherer;
  2564. };
  2565. // start gathering from an RTCIceGatherer.
  2566. RTCPeerConnection.prototype._gather = function(mid, sdpMLineIndex) {
  2567. var pc = this;
  2568. var iceGatherer = this.transceivers[sdpMLineIndex].iceGatherer;
  2569. if (iceGatherer.onlocalcandidate) {
  2570. return;
  2571. }
  2572. var bufferedCandidateEvents =
  2573. this.transceivers[sdpMLineIndex].bufferedCandidateEvents;
  2574. this.transceivers[sdpMLineIndex].bufferedCandidateEvents = null;
  2575. iceGatherer.removeEventListener('localcandidate',
  2576. this.transceivers[sdpMLineIndex].bufferCandidates);
  2577. iceGatherer.onlocalcandidate = function(evt) {
  2578. if (pc.usingBundle && sdpMLineIndex > 0) {
  2579. // if we know that we use bundle we can drop candidates with
  2580. // ѕdpMLineIndex > 0. If we don't do this then our state gets
  2581. // confused since we dispose the extra ice gatherer.
  2582. return;
  2583. }
  2584. var event = new Event('icecandidate');
  2585. event.candidate = {sdpMid: mid, sdpMLineIndex: sdpMLineIndex};
  2586. var cand = evt.candidate;
  2587. // Edge emits an empty object for RTCIceCandidateComplete‥
  2588. var end = !cand || Object.keys(cand).length === 0;
  2589. if (end) {
  2590. // polyfill since RTCIceGatherer.state is not implemented in
  2591. // Edge 10547 yet.
  2592. if (iceGatherer.state === 'new' || iceGatherer.state === 'gathering') {
  2593. iceGatherer.state = 'completed';
  2594. }
  2595. } else {
  2596. if (iceGatherer.state === 'new') {
  2597. iceGatherer.state = 'gathering';
  2598. }
  2599. // RTCIceCandidate doesn't have a component, needs to be added
  2600. cand.component = 1;
  2601. // also the usernameFragment. TODO: update SDP to take both variants.
  2602. cand.ufrag = iceGatherer.getLocalParameters().usernameFragment;
  2603. var serializedCandidate = sdp.writeCandidate(cand);
  2604. event.candidate = Object.assign(event.candidate,
  2605. sdp.parseCandidate(serializedCandidate));
  2606. event.candidate.candidate = serializedCandidate;
  2607. event.candidate.toJSON = function() {
  2608. return {
  2609. candidate: event.candidate.candidate,
  2610. sdpMid: event.candidate.sdpMid,
  2611. sdpMLineIndex: event.candidate.sdpMLineIndex,
  2612. usernameFragment: event.candidate.usernameFragment
  2613. };
  2614. };
  2615. }
  2616. // update local description.
  2617. var sections = sdp.getMediaSections(pc._localDescription.sdp);
  2618. if (!end) {
  2619. sections[event.candidate.sdpMLineIndex] +=
  2620. 'a=' + event.candidate.candidate + '\r\n';
  2621. } else {
  2622. sections[event.candidate.sdpMLineIndex] +=
  2623. 'a=end-of-candidates\r\n';
  2624. }
  2625. pc._localDescription.sdp =
  2626. sdp.getDescription(pc._localDescription.sdp) +
  2627. sections.join('');
  2628. var complete = pc.transceivers.every(function(transceiver) {
  2629. return transceiver.iceGatherer &&
  2630. transceiver.iceGatherer.state === 'completed';
  2631. });
  2632. if (pc.iceGatheringState !== 'gathering') {
  2633. pc.iceGatheringState = 'gathering';
  2634. pc._emitGatheringStateChange();
  2635. }
  2636. // Emit candidate. Also emit null candidate when all gatherers are
  2637. // complete.
  2638. if (!end) {
  2639. pc._dispatchEvent('icecandidate', event);
  2640. }
  2641. if (complete) {
  2642. pc._dispatchEvent('icecandidate', new Event('icecandidate'));
  2643. pc.iceGatheringState = 'complete';
  2644. pc._emitGatheringStateChange();
  2645. }
  2646. };
  2647. // emit already gathered candidates.
  2648. window.setTimeout(function() {
  2649. bufferedCandidateEvents.forEach(function(e) {
  2650. iceGatherer.onlocalcandidate(e);
  2651. });
  2652. }, 0);
  2653. };
  2654. // Create ICE transport and DTLS transport.
  2655. RTCPeerConnection.prototype._createIceAndDtlsTransports = function() {
  2656. var pc = this;
  2657. var iceTransport = new window.RTCIceTransport(null);
  2658. iceTransport.onicestatechange = function() {
  2659. pc._updateIceConnectionState();
  2660. pc._updateConnectionState();
  2661. };
  2662. var dtlsTransport = new window.RTCDtlsTransport(iceTransport);
  2663. dtlsTransport.ondtlsstatechange = function() {
  2664. pc._updateConnectionState();
  2665. };
  2666. dtlsTransport.onerror = function() {
  2667. // onerror does not set state to failed by itself.
  2668. Object.defineProperty(dtlsTransport, 'state',
  2669. {value: 'failed', writable: true});
  2670. pc._updateConnectionState();
  2671. };
  2672. return {
  2673. iceTransport: iceTransport,
  2674. dtlsTransport: dtlsTransport
  2675. };
  2676. };
  2677. // Destroy ICE gatherer, ICE transport and DTLS transport.
  2678. // Without triggering the callbacks.
  2679. RTCPeerConnection.prototype._disposeIceAndDtlsTransports = function(
  2680. sdpMLineIndex) {
  2681. var iceGatherer = this.transceivers[sdpMLineIndex].iceGatherer;
  2682. if (iceGatherer) {
  2683. delete iceGatherer.onlocalcandidate;
  2684. delete this.transceivers[sdpMLineIndex].iceGatherer;
  2685. }
  2686. var iceTransport = this.transceivers[sdpMLineIndex].iceTransport;
  2687. if (iceTransport) {
  2688. delete iceTransport.onicestatechange;
  2689. delete this.transceivers[sdpMLineIndex].iceTransport;
  2690. }
  2691. var dtlsTransport = this.transceivers[sdpMLineIndex].dtlsTransport;
  2692. if (dtlsTransport) {
  2693. delete dtlsTransport.ondtlsstatechange;
  2694. delete dtlsTransport.onerror;
  2695. delete this.transceivers[sdpMLineIndex].dtlsTransport;
  2696. }
  2697. };
  2698. // Start the RTP Sender and Receiver for a transceiver.
  2699. RTCPeerConnection.prototype._transceive = function(transceiver,
  2700. send, recv) {
  2701. var params = getCommonCapabilities(transceiver.localCapabilities,
  2702. transceiver.remoteCapabilities);
  2703. if (send && transceiver.rtpSender) {
  2704. params.encodings = transceiver.sendEncodingParameters;
  2705. params.rtcp = {
  2706. cname: sdp.localCName,
  2707. compound: transceiver.rtcpParameters.compound
  2708. };
  2709. if (transceiver.recvEncodingParameters.length) {
  2710. params.rtcp.ssrc = transceiver.recvEncodingParameters[0].ssrc;
  2711. }
  2712. transceiver.rtpSender.send(params);
  2713. }
  2714. if (recv && transceiver.rtpReceiver && params.codecs.length > 0) {
  2715. // remove RTX field in Edge 14942
  2716. if (transceiver.kind === 'video'
  2717. && transceiver.recvEncodingParameters
  2718. && edgeVersion < 15019) {
  2719. transceiver.recvEncodingParameters.forEach(function(p) {
  2720. delete p.rtx;
  2721. });
  2722. }
  2723. if (transceiver.recvEncodingParameters.length) {
  2724. params.encodings = transceiver.recvEncodingParameters;
  2725. } else {
  2726. params.encodings = [{}];
  2727. }
  2728. params.rtcp = {
  2729. compound: transceiver.rtcpParameters.compound
  2730. };
  2731. if (transceiver.rtcpParameters.cname) {
  2732. params.rtcp.cname = transceiver.rtcpParameters.cname;
  2733. }
  2734. if (transceiver.sendEncodingParameters.length) {
  2735. params.rtcp.ssrc = transceiver.sendEncodingParameters[0].ssrc;
  2736. }
  2737. transceiver.rtpReceiver.receive(params);
  2738. }
  2739. };
  2740. RTCPeerConnection.prototype.setLocalDescription = function(description) {
  2741. var pc = this;
  2742. // Note: pranswer is not supported.
  2743. if (['offer', 'answer'].indexOf(description.type) === -1) {
  2744. return Promise.reject(makeError('TypeError',
  2745. 'Unsupported type "' + description.type + '"'));
  2746. }
  2747. if (!isActionAllowedInSignalingState('setLocalDescription',
  2748. description.type, pc.signalingState) || pc._isClosed) {
  2749. return Promise.reject(makeError('InvalidStateError',
  2750. 'Can not set local ' + description.type +
  2751. ' in state ' + pc.signalingState));
  2752. }
  2753. var sections;
  2754. var sessionpart;
  2755. if (description.type === 'offer') {
  2756. // VERY limited support for SDP munging. Limited to:
  2757. // * changing the order of codecs
  2758. sections = sdp.splitSections(description.sdp);
  2759. sessionpart = sections.shift();
  2760. sections.forEach(function(mediaSection, sdpMLineIndex) {
  2761. var caps = sdp.parseRtpParameters(mediaSection);
  2762. pc.transceivers[sdpMLineIndex].localCapabilities = caps;
  2763. });
  2764. pc.transceivers.forEach(function(transceiver, sdpMLineIndex) {
  2765. pc._gather(transceiver.mid, sdpMLineIndex);
  2766. });
  2767. } else if (description.type === 'answer') {
  2768. sections = sdp.splitSections(pc._remoteDescription.sdp);
  2769. sessionpart = sections.shift();
  2770. var isIceLite = sdp.matchPrefix(sessionpart,
  2771. 'a=ice-lite').length > 0;
  2772. sections.forEach(function(mediaSection, sdpMLineIndex) {
  2773. var transceiver = pc.transceivers[sdpMLineIndex];
  2774. var iceGatherer = transceiver.iceGatherer;
  2775. var iceTransport = transceiver.iceTransport;
  2776. var dtlsTransport = transceiver.dtlsTransport;
  2777. var localCapabilities = transceiver.localCapabilities;
  2778. var remoteCapabilities = transceiver.remoteCapabilities;
  2779. // treat bundle-only as not-rejected.
  2780. var rejected = sdp.isRejected(mediaSection) &&
  2781. sdp.matchPrefix(mediaSection, 'a=bundle-only').length === 0;
  2782. if (!rejected && !transceiver.rejected) {
  2783. var remoteIceParameters = sdp.getIceParameters(
  2784. mediaSection, sessionpart);
  2785. var remoteDtlsParameters = sdp.getDtlsParameters(
  2786. mediaSection, sessionpart);
  2787. if (isIceLite) {
  2788. remoteDtlsParameters.role = 'server';
  2789. }
  2790. if (!pc.usingBundle || sdpMLineIndex === 0) {
  2791. pc._gather(transceiver.mid, sdpMLineIndex);
  2792. if (iceTransport.state === 'new') {
  2793. iceTransport.start(iceGatherer, remoteIceParameters,
  2794. isIceLite ? 'controlling' : 'controlled');
  2795. }
  2796. if (dtlsTransport.state === 'new') {
  2797. dtlsTransport.start(remoteDtlsParameters);
  2798. }
  2799. }
  2800. // Calculate intersection of capabilities.
  2801. var params = getCommonCapabilities(localCapabilities,
  2802. remoteCapabilities);
  2803. // Start the RTCRtpSender. The RTCRtpReceiver for this
  2804. // transceiver has already been started in setRemoteDescription.
  2805. pc._transceive(transceiver,
  2806. params.codecs.length > 0,
  2807. false);
  2808. }
  2809. });
  2810. }
  2811. pc._localDescription = {
  2812. type: description.type,
  2813. sdp: description.sdp
  2814. };
  2815. if (description.type === 'offer') {
  2816. pc._updateSignalingState('have-local-offer');
  2817. } else {
  2818. pc._updateSignalingState('stable');
  2819. }
  2820. return Promise.resolve();
  2821. };
  2822. RTCPeerConnection.prototype.setRemoteDescription = function(description) {
  2823. var pc = this;
  2824. // Note: pranswer is not supported.
  2825. if (['offer', 'answer'].indexOf(description.type) === -1) {
  2826. return Promise.reject(makeError('TypeError',
  2827. 'Unsupported type "' + description.type + '"'));
  2828. }
  2829. if (!isActionAllowedInSignalingState('setRemoteDescription',
  2830. description.type, pc.signalingState) || pc._isClosed) {
  2831. return Promise.reject(makeError('InvalidStateError',
  2832. 'Can not set remote ' + description.type +
  2833. ' in state ' + pc.signalingState));
  2834. }
  2835. var streams = {};
  2836. pc.remoteStreams.forEach(function(stream) {
  2837. streams[stream.id] = stream;
  2838. });
  2839. var receiverList = [];
  2840. var sections = sdp.splitSections(description.sdp);
  2841. var sessionpart = sections.shift();
  2842. var isIceLite = sdp.matchPrefix(sessionpart,
  2843. 'a=ice-lite').length > 0;
  2844. var usingBundle = sdp.matchPrefix(sessionpart,
  2845. 'a=group:BUNDLE ').length > 0;
  2846. pc.usingBundle = usingBundle;
  2847. var iceOptions = sdp.matchPrefix(sessionpart,
  2848. 'a=ice-options:')[0];
  2849. if (iceOptions) {
  2850. pc.canTrickleIceCandidates = iceOptions.substr(14).split(' ')
  2851. .indexOf('trickle') >= 0;
  2852. } else {
  2853. pc.canTrickleIceCandidates = false;
  2854. }
  2855. sections.forEach(function(mediaSection, sdpMLineIndex) {
  2856. var lines = sdp.splitLines(mediaSection);
  2857. var kind = sdp.getKind(mediaSection);
  2858. // treat bundle-only as not-rejected.
  2859. var rejected = sdp.isRejected(mediaSection) &&
  2860. sdp.matchPrefix(mediaSection, 'a=bundle-only').length === 0;
  2861. var protocol = lines[0].substr(2).split(' ')[2];
  2862. var direction = sdp.getDirection(mediaSection, sessionpart);
  2863. var remoteMsid = sdp.parseMsid(mediaSection);
  2864. var mid = sdp.getMid(mediaSection) || sdp.generateIdentifier();
  2865. // Reject datachannels which are not implemented yet.
  2866. if (rejected || (kind === 'application' && (protocol === 'DTLS/SCTP' ||
  2867. protocol === 'UDP/DTLS/SCTP'))) {
  2868. // TODO: this is dangerous in the case where a non-rejected m-line
  2869. // becomes rejected.
  2870. pc.transceivers[sdpMLineIndex] = {
  2871. mid: mid,
  2872. kind: kind,
  2873. protocol: protocol,
  2874. rejected: true
  2875. };
  2876. return;
  2877. }
  2878. if (!rejected && pc.transceivers[sdpMLineIndex] &&
  2879. pc.transceivers[sdpMLineIndex].rejected) {
  2880. // recycle a rejected transceiver.
  2881. pc.transceivers[sdpMLineIndex] = pc._createTransceiver(kind, true);
  2882. }
  2883. var transceiver;
  2884. var iceGatherer;
  2885. var iceTransport;
  2886. var dtlsTransport;
  2887. var rtpReceiver;
  2888. var sendEncodingParameters;
  2889. var recvEncodingParameters;
  2890. var localCapabilities;
  2891. var track;
  2892. // FIXME: ensure the mediaSection has rtcp-mux set.
  2893. var remoteCapabilities = sdp.parseRtpParameters(mediaSection);
  2894. var remoteIceParameters;
  2895. var remoteDtlsParameters;
  2896. if (!rejected) {
  2897. remoteIceParameters = sdp.getIceParameters(mediaSection,
  2898. sessionpart);
  2899. remoteDtlsParameters = sdp.getDtlsParameters(mediaSection,
  2900. sessionpart);
  2901. remoteDtlsParameters.role = 'client';
  2902. }
  2903. recvEncodingParameters =
  2904. sdp.parseRtpEncodingParameters(mediaSection);
  2905. var rtcpParameters = sdp.parseRtcpParameters(mediaSection);
  2906. var isComplete = sdp.matchPrefix(mediaSection,
  2907. 'a=end-of-candidates', sessionpart).length > 0;
  2908. var cands = sdp.matchPrefix(mediaSection, 'a=candidate:')
  2909. .map(function(cand) {
  2910. return sdp.parseCandidate(cand);
  2911. })
  2912. .filter(function(cand) {
  2913. return cand.component === 1;
  2914. });
  2915. // Check if we can use BUNDLE and dispose transports.
  2916. if ((description.type === 'offer' || description.type === 'answer') &&
  2917. !rejected && usingBundle && sdpMLineIndex > 0 &&
  2918. pc.transceivers[sdpMLineIndex]) {
  2919. pc._disposeIceAndDtlsTransports(sdpMLineIndex);
  2920. pc.transceivers[sdpMLineIndex].iceGatherer =
  2921. pc.transceivers[0].iceGatherer;
  2922. pc.transceivers[sdpMLineIndex].iceTransport =
  2923. pc.transceivers[0].iceTransport;
  2924. pc.transceivers[sdpMLineIndex].dtlsTransport =
  2925. pc.transceivers[0].dtlsTransport;
  2926. if (pc.transceivers[sdpMLineIndex].rtpSender) {
  2927. pc.transceivers[sdpMLineIndex].rtpSender.setTransport(
  2928. pc.transceivers[0].dtlsTransport);
  2929. }
  2930. if (pc.transceivers[sdpMLineIndex].rtpReceiver) {
  2931. pc.transceivers[sdpMLineIndex].rtpReceiver.setTransport(
  2932. pc.transceivers[0].dtlsTransport);
  2933. }
  2934. }
  2935. if (description.type === 'offer' && !rejected) {
  2936. transceiver = pc.transceivers[sdpMLineIndex] ||
  2937. pc._createTransceiver(kind);
  2938. transceiver.mid = mid;
  2939. if (!transceiver.iceGatherer) {
  2940. transceiver.iceGatherer = pc._createIceGatherer(sdpMLineIndex,
  2941. usingBundle);
  2942. }
  2943. if (cands.length && transceiver.iceTransport.state === 'new') {
  2944. if (isComplete && (!usingBundle || sdpMLineIndex === 0)) {
  2945. transceiver.iceTransport.setRemoteCandidates(cands);
  2946. } else {
  2947. cands.forEach(function(candidate) {
  2948. maybeAddCandidate(transceiver.iceTransport, candidate);
  2949. });
  2950. }
  2951. }
  2952. localCapabilities = window.RTCRtpReceiver.getCapabilities(kind);
  2953. // filter RTX until additional stuff needed for RTX is implemented
  2954. // in adapter.js
  2955. if (edgeVersion < 15019) {
  2956. localCapabilities.codecs = localCapabilities.codecs.filter(
  2957. function(codec) {
  2958. return codec.name !== 'rtx';
  2959. });
  2960. }
  2961. sendEncodingParameters = transceiver.sendEncodingParameters || [{
  2962. ssrc: (2 * sdpMLineIndex + 2) * 1001
  2963. }];
  2964. // TODO: rewrite to use http://w3c.github.io/webrtc-pc/#set-associated-remote-streams
  2965. var isNewTrack = false;
  2966. if (direction === 'sendrecv' || direction === 'sendonly') {
  2967. isNewTrack = !transceiver.rtpReceiver;
  2968. rtpReceiver = transceiver.rtpReceiver ||
  2969. new window.RTCRtpReceiver(transceiver.dtlsTransport, kind);
  2970. if (isNewTrack) {
  2971. var stream;
  2972. track = rtpReceiver.track;
  2973. // FIXME: does not work with Plan B.
  2974. if (remoteMsid && remoteMsid.stream === '-') ; else if (remoteMsid) {
  2975. if (!streams[remoteMsid.stream]) {
  2976. streams[remoteMsid.stream] = new window.MediaStream();
  2977. Object.defineProperty(streams[remoteMsid.stream], 'id', {
  2978. get: function() {
  2979. return remoteMsid.stream;
  2980. }
  2981. });
  2982. }
  2983. Object.defineProperty(track, 'id', {
  2984. get: function() {
  2985. return remoteMsid.track;
  2986. }
  2987. });
  2988. stream = streams[remoteMsid.stream];
  2989. } else {
  2990. if (!streams.default) {
  2991. streams.default = new window.MediaStream();
  2992. }
  2993. stream = streams.default;
  2994. }
  2995. if (stream) {
  2996. addTrackToStreamAndFireEvent(track, stream);
  2997. transceiver.associatedRemoteMediaStreams.push(stream);
  2998. }
  2999. receiverList.push([track, rtpReceiver, stream]);
  3000. }
  3001. } else if (transceiver.rtpReceiver && transceiver.rtpReceiver.track) {
  3002. transceiver.associatedRemoteMediaStreams.forEach(function(s) {
  3003. var nativeTrack = s.getTracks().find(function(t) {
  3004. return t.id === transceiver.rtpReceiver.track.id;
  3005. });
  3006. if (nativeTrack) {
  3007. removeTrackFromStreamAndFireEvent(nativeTrack, s);
  3008. }
  3009. });
  3010. transceiver.associatedRemoteMediaStreams = [];
  3011. }
  3012. transceiver.localCapabilities = localCapabilities;
  3013. transceiver.remoteCapabilities = remoteCapabilities;
  3014. transceiver.rtpReceiver = rtpReceiver;
  3015. transceiver.rtcpParameters = rtcpParameters;
  3016. transceiver.sendEncodingParameters = sendEncodingParameters;
  3017. transceiver.recvEncodingParameters = recvEncodingParameters;
  3018. // Start the RTCRtpReceiver now. The RTPSender is started in
  3019. // setLocalDescription.
  3020. pc._transceive(pc.transceivers[sdpMLineIndex],
  3021. false,
  3022. isNewTrack);
  3023. } else if (description.type === 'answer' && !rejected) {
  3024. transceiver = pc.transceivers[sdpMLineIndex];
  3025. iceGatherer = transceiver.iceGatherer;
  3026. iceTransport = transceiver.iceTransport;
  3027. dtlsTransport = transceiver.dtlsTransport;
  3028. rtpReceiver = transceiver.rtpReceiver;
  3029. sendEncodingParameters = transceiver.sendEncodingParameters;
  3030. localCapabilities = transceiver.localCapabilities;
  3031. pc.transceivers[sdpMLineIndex].recvEncodingParameters =
  3032. recvEncodingParameters;
  3033. pc.transceivers[sdpMLineIndex].remoteCapabilities =
  3034. remoteCapabilities;
  3035. pc.transceivers[sdpMLineIndex].rtcpParameters = rtcpParameters;
  3036. if (cands.length && iceTransport.state === 'new') {
  3037. if ((isIceLite || isComplete) &&
  3038. (!usingBundle || sdpMLineIndex === 0)) {
  3039. iceTransport.setRemoteCandidates(cands);
  3040. } else {
  3041. cands.forEach(function(candidate) {
  3042. maybeAddCandidate(transceiver.iceTransport, candidate);
  3043. });
  3044. }
  3045. }
  3046. if (!usingBundle || sdpMLineIndex === 0) {
  3047. if (iceTransport.state === 'new') {
  3048. iceTransport.start(iceGatherer, remoteIceParameters,
  3049. 'controlling');
  3050. }
  3051. if (dtlsTransport.state === 'new') {
  3052. dtlsTransport.start(remoteDtlsParameters);
  3053. }
  3054. }
  3055. // If the offer contained RTX but the answer did not,
  3056. // remove RTX from sendEncodingParameters.
  3057. var commonCapabilities = getCommonCapabilities(
  3058. transceiver.localCapabilities,
  3059. transceiver.remoteCapabilities);
  3060. var hasRtx = commonCapabilities.codecs.filter(function(c) {
  3061. return c.name.toLowerCase() === 'rtx';
  3062. }).length;
  3063. if (!hasRtx && transceiver.sendEncodingParameters[0].rtx) {
  3064. delete transceiver.sendEncodingParameters[0].rtx;
  3065. }
  3066. pc._transceive(transceiver,
  3067. direction === 'sendrecv' || direction === 'recvonly',
  3068. direction === 'sendrecv' || direction === 'sendonly');
  3069. // TODO: rewrite to use http://w3c.github.io/webrtc-pc/#set-associated-remote-streams
  3070. if (rtpReceiver &&
  3071. (direction === 'sendrecv' || direction === 'sendonly')) {
  3072. track = rtpReceiver.track;
  3073. if (remoteMsid) {
  3074. if (!streams[remoteMsid.stream]) {
  3075. streams[remoteMsid.stream] = new window.MediaStream();
  3076. }
  3077. addTrackToStreamAndFireEvent(track, streams[remoteMsid.stream]);
  3078. receiverList.push([track, rtpReceiver, streams[remoteMsid.stream]]);
  3079. } else {
  3080. if (!streams.default) {
  3081. streams.default = new window.MediaStream();
  3082. }
  3083. addTrackToStreamAndFireEvent(track, streams.default);
  3084. receiverList.push([track, rtpReceiver, streams.default]);
  3085. }
  3086. } else {
  3087. // FIXME: actually the receiver should be created later.
  3088. delete transceiver.rtpReceiver;
  3089. }
  3090. }
  3091. });
  3092. if (pc._dtlsRole === undefined) {
  3093. pc._dtlsRole = description.type === 'offer' ? 'active' : 'passive';
  3094. }
  3095. pc._remoteDescription = {
  3096. type: description.type,
  3097. sdp: description.sdp
  3098. };
  3099. if (description.type === 'offer') {
  3100. pc._updateSignalingState('have-remote-offer');
  3101. } else {
  3102. pc._updateSignalingState('stable');
  3103. }
  3104. Object.keys(streams).forEach(function(sid) {
  3105. var stream = streams[sid];
  3106. if (stream.getTracks().length) {
  3107. if (pc.remoteStreams.indexOf(stream) === -1) {
  3108. pc.remoteStreams.push(stream);
  3109. var event = new Event('addstream');
  3110. event.stream = stream;
  3111. window.setTimeout(function() {
  3112. pc._dispatchEvent('addstream', event);
  3113. });
  3114. }
  3115. receiverList.forEach(function(item) {
  3116. var track = item[0];
  3117. var receiver = item[1];
  3118. if (stream.id !== item[2].id) {
  3119. return;
  3120. }
  3121. fireAddTrack(pc, track, receiver, [stream]);
  3122. });
  3123. }
  3124. });
  3125. receiverList.forEach(function(item) {
  3126. if (item[2]) {
  3127. return;
  3128. }
  3129. fireAddTrack(pc, item[0], item[1], []);
  3130. });
  3131. // check whether addIceCandidate({}) was called within four seconds after
  3132. // setRemoteDescription.
  3133. window.setTimeout(function() {
  3134. if (!(pc && pc.transceivers)) {
  3135. return;
  3136. }
  3137. pc.transceivers.forEach(function(transceiver) {
  3138. if (transceiver.iceTransport &&
  3139. transceiver.iceTransport.state === 'new' &&
  3140. transceiver.iceTransport.getRemoteCandidates().length > 0) {
  3141. console.warn('Timeout for addRemoteCandidate. Consider sending ' +
  3142. 'an end-of-candidates notification');
  3143. transceiver.iceTransport.addRemoteCandidate({});
  3144. }
  3145. });
  3146. }, 4000);
  3147. return Promise.resolve();
  3148. };
  3149. RTCPeerConnection.prototype.close = function() {
  3150. this.transceivers.forEach(function(transceiver) {
  3151. /* not yet
  3152. if (transceiver.iceGatherer) {
  3153. transceiver.iceGatherer.close();
  3154. }
  3155. */
  3156. if (transceiver.iceTransport) {
  3157. transceiver.iceTransport.stop();
  3158. }
  3159. if (transceiver.dtlsTransport) {
  3160. transceiver.dtlsTransport.stop();
  3161. }
  3162. if (transceiver.rtpSender) {
  3163. transceiver.rtpSender.stop();
  3164. }
  3165. if (transceiver.rtpReceiver) {
  3166. transceiver.rtpReceiver.stop();
  3167. }
  3168. });
  3169. // FIXME: clean up tracks, local streams, remote streams, etc
  3170. this._isClosed = true;
  3171. this._updateSignalingState('closed');
  3172. };
  3173. // Update the signaling state.
  3174. RTCPeerConnection.prototype._updateSignalingState = function(newState) {
  3175. this.signalingState = newState;
  3176. var event = new Event('signalingstatechange');
  3177. this._dispatchEvent('signalingstatechange', event);
  3178. };
  3179. // Determine whether to fire the negotiationneeded event.
  3180. RTCPeerConnection.prototype._maybeFireNegotiationNeeded = function() {
  3181. var pc = this;
  3182. if (this.signalingState !== 'stable' || this.needNegotiation === true) {
  3183. return;
  3184. }
  3185. this.needNegotiation = true;
  3186. window.setTimeout(function() {
  3187. if (pc.needNegotiation) {
  3188. pc.needNegotiation = false;
  3189. var event = new Event('negotiationneeded');
  3190. pc._dispatchEvent('negotiationneeded', event);
  3191. }
  3192. }, 0);
  3193. };
  3194. // Update the ice connection state.
  3195. RTCPeerConnection.prototype._updateIceConnectionState = function() {
  3196. var newState;
  3197. var states = {
  3198. 'new': 0,
  3199. closed: 0,
  3200. checking: 0,
  3201. connected: 0,
  3202. completed: 0,
  3203. disconnected: 0,
  3204. failed: 0
  3205. };
  3206. this.transceivers.forEach(function(transceiver) {
  3207. if (transceiver.iceTransport && !transceiver.rejected) {
  3208. states[transceiver.iceTransport.state]++;
  3209. }
  3210. });
  3211. newState = 'new';
  3212. if (states.failed > 0) {
  3213. newState = 'failed';
  3214. } else if (states.checking > 0) {
  3215. newState = 'checking';
  3216. } else if (states.disconnected > 0) {
  3217. newState = 'disconnected';
  3218. } else if (states.new > 0) {
  3219. newState = 'new';
  3220. } else if (states.connected > 0) {
  3221. newState = 'connected';
  3222. } else if (states.completed > 0) {
  3223. newState = 'completed';
  3224. }
  3225. if (newState !== this.iceConnectionState) {
  3226. this.iceConnectionState = newState;
  3227. var event = new Event('iceconnectionstatechange');
  3228. this._dispatchEvent('iceconnectionstatechange', event);
  3229. }
  3230. };
  3231. // Update the connection state.
  3232. RTCPeerConnection.prototype._updateConnectionState = function() {
  3233. var newState;
  3234. var states = {
  3235. 'new': 0,
  3236. closed: 0,
  3237. connecting: 0,
  3238. connected: 0,
  3239. completed: 0,
  3240. disconnected: 0,
  3241. failed: 0
  3242. };
  3243. this.transceivers.forEach(function(transceiver) {
  3244. if (transceiver.iceTransport && transceiver.dtlsTransport &&
  3245. !transceiver.rejected) {
  3246. states[transceiver.iceTransport.state]++;
  3247. states[transceiver.dtlsTransport.state]++;
  3248. }
  3249. });
  3250. // ICETransport.completed and connected are the same for this purpose.
  3251. states.connected += states.completed;
  3252. newState = 'new';
  3253. if (states.failed > 0) {
  3254. newState = 'failed';
  3255. } else if (states.connecting > 0) {
  3256. newState = 'connecting';
  3257. } else if (states.disconnected > 0) {
  3258. newState = 'disconnected';
  3259. } else if (states.new > 0) {
  3260. newState = 'new';
  3261. } else if (states.connected > 0) {
  3262. newState = 'connected';
  3263. }
  3264. if (newState !== this.connectionState) {
  3265. this.connectionState = newState;
  3266. var event = new Event('connectionstatechange');
  3267. this._dispatchEvent('connectionstatechange', event);
  3268. }
  3269. };
  3270. RTCPeerConnection.prototype.createOffer = function() {
  3271. var pc = this;
  3272. if (pc._isClosed) {
  3273. return Promise.reject(makeError('InvalidStateError',
  3274. 'Can not call createOffer after close'));
  3275. }
  3276. var numAudioTracks = pc.transceivers.filter(function(t) {
  3277. return t.kind === 'audio';
  3278. }).length;
  3279. var numVideoTracks = pc.transceivers.filter(function(t) {
  3280. return t.kind === 'video';
  3281. }).length;
  3282. // Determine number of audio and video tracks we need to send/recv.
  3283. var offerOptions = arguments[0];
  3284. if (offerOptions) {
  3285. // Reject Chrome legacy constraints.
  3286. if (offerOptions.mandatory || offerOptions.optional) {
  3287. throw new TypeError(
  3288. 'Legacy mandatory/optional constraints not supported.');
  3289. }
  3290. if (offerOptions.offerToReceiveAudio !== undefined) {
  3291. if (offerOptions.offerToReceiveAudio === true) {
  3292. numAudioTracks = 1;
  3293. } else if (offerOptions.offerToReceiveAudio === false) {
  3294. numAudioTracks = 0;
  3295. } else {
  3296. numAudioTracks = offerOptions.offerToReceiveAudio;
  3297. }
  3298. }
  3299. if (offerOptions.offerToReceiveVideo !== undefined) {
  3300. if (offerOptions.offerToReceiveVideo === true) {
  3301. numVideoTracks = 1;
  3302. } else if (offerOptions.offerToReceiveVideo === false) {
  3303. numVideoTracks = 0;
  3304. } else {
  3305. numVideoTracks = offerOptions.offerToReceiveVideo;
  3306. }
  3307. }
  3308. }
  3309. pc.transceivers.forEach(function(transceiver) {
  3310. if (transceiver.kind === 'audio') {
  3311. numAudioTracks--;
  3312. if (numAudioTracks < 0) {
  3313. transceiver.wantReceive = false;
  3314. }
  3315. } else if (transceiver.kind === 'video') {
  3316. numVideoTracks--;
  3317. if (numVideoTracks < 0) {
  3318. transceiver.wantReceive = false;
  3319. }
  3320. }
  3321. });
  3322. // Create M-lines for recvonly streams.
  3323. while (numAudioTracks > 0 || numVideoTracks > 0) {
  3324. if (numAudioTracks > 0) {
  3325. pc._createTransceiver('audio');
  3326. numAudioTracks--;
  3327. }
  3328. if (numVideoTracks > 0) {
  3329. pc._createTransceiver('video');
  3330. numVideoTracks--;
  3331. }
  3332. }
  3333. var sdp$1 = sdp.writeSessionBoilerplate(pc._sdpSessionId,
  3334. pc._sdpSessionVersion++);
  3335. pc.transceivers.forEach(function(transceiver, sdpMLineIndex) {
  3336. // For each track, create an ice gatherer, ice transport,
  3337. // dtls transport, potentially rtpsender and rtpreceiver.
  3338. var track = transceiver.track;
  3339. var kind = transceiver.kind;
  3340. var mid = transceiver.mid || sdp.generateIdentifier();
  3341. transceiver.mid = mid;
  3342. if (!transceiver.iceGatherer) {
  3343. transceiver.iceGatherer = pc._createIceGatherer(sdpMLineIndex,
  3344. pc.usingBundle);
  3345. }
  3346. var localCapabilities = window.RTCRtpSender.getCapabilities(kind);
  3347. // filter RTX until additional stuff needed for RTX is implemented
  3348. // in adapter.js
  3349. if (edgeVersion < 15019) {
  3350. localCapabilities.codecs = localCapabilities.codecs.filter(
  3351. function(codec) {
  3352. return codec.name !== 'rtx';
  3353. });
  3354. }
  3355. localCapabilities.codecs.forEach(function(codec) {
  3356. // work around https://bugs.chromium.org/p/webrtc/issues/detail?id=6552
  3357. // by adding level-asymmetry-allowed=1
  3358. if (codec.name === 'H264' &&
  3359. codec.parameters['level-asymmetry-allowed'] === undefined) {
  3360. codec.parameters['level-asymmetry-allowed'] = '1';
  3361. }
  3362. // for subsequent offers, we might have to re-use the payload
  3363. // type of the last offer.
  3364. if (transceiver.remoteCapabilities &&
  3365. transceiver.remoteCapabilities.codecs) {
  3366. transceiver.remoteCapabilities.codecs.forEach(function(remoteCodec) {
  3367. if (codec.name.toLowerCase() === remoteCodec.name.toLowerCase() &&
  3368. codec.clockRate === remoteCodec.clockRate) {
  3369. codec.preferredPayloadType = remoteCodec.payloadType;
  3370. }
  3371. });
  3372. }
  3373. });
  3374. localCapabilities.headerExtensions.forEach(function(hdrExt) {
  3375. var remoteExtensions = transceiver.remoteCapabilities &&
  3376. transceiver.remoteCapabilities.headerExtensions || [];
  3377. remoteExtensions.forEach(function(rHdrExt) {
  3378. if (hdrExt.uri === rHdrExt.uri) {
  3379. hdrExt.id = rHdrExt.id;
  3380. }
  3381. });
  3382. });
  3383. // generate an ssrc now, to be used later in rtpSender.send
  3384. var sendEncodingParameters = transceiver.sendEncodingParameters || [{
  3385. ssrc: (2 * sdpMLineIndex + 1) * 1001
  3386. }];
  3387. if (track) {
  3388. // add RTX
  3389. if (edgeVersion >= 15019 && kind === 'video' &&
  3390. !sendEncodingParameters[0].rtx) {
  3391. sendEncodingParameters[0].rtx = {
  3392. ssrc: sendEncodingParameters[0].ssrc + 1
  3393. };
  3394. }
  3395. }
  3396. if (transceiver.wantReceive) {
  3397. transceiver.rtpReceiver = new window.RTCRtpReceiver(
  3398. transceiver.dtlsTransport, kind);
  3399. }
  3400. transceiver.localCapabilities = localCapabilities;
  3401. transceiver.sendEncodingParameters = sendEncodingParameters;
  3402. });
  3403. // always offer BUNDLE and dispose on return if not supported.
  3404. if (pc._config.bundlePolicy !== 'max-compat') {
  3405. sdp$1 += 'a=group:BUNDLE ' + pc.transceivers.map(function(t) {
  3406. return t.mid;
  3407. }).join(' ') + '\r\n';
  3408. }
  3409. sdp$1 += 'a=ice-options:trickle\r\n';
  3410. pc.transceivers.forEach(function(transceiver, sdpMLineIndex) {
  3411. sdp$1 += writeMediaSection(transceiver, transceiver.localCapabilities,
  3412. 'offer', transceiver.stream, pc._dtlsRole);
  3413. sdp$1 += 'a=rtcp-rsize\r\n';
  3414. if (transceiver.iceGatherer && pc.iceGatheringState !== 'new' &&
  3415. (sdpMLineIndex === 0 || !pc.usingBundle)) {
  3416. transceiver.iceGatherer.getLocalCandidates().forEach(function(cand) {
  3417. cand.component = 1;
  3418. sdp$1 += 'a=' + sdp.writeCandidate(cand) + '\r\n';
  3419. });
  3420. if (transceiver.iceGatherer.state === 'completed') {
  3421. sdp$1 += 'a=end-of-candidates\r\n';
  3422. }
  3423. }
  3424. });
  3425. var desc = new window.RTCSessionDescription({
  3426. type: 'offer',
  3427. sdp: sdp$1
  3428. });
  3429. return Promise.resolve(desc);
  3430. };
  3431. RTCPeerConnection.prototype.createAnswer = function() {
  3432. var pc = this;
  3433. if (pc._isClosed) {
  3434. return Promise.reject(makeError('InvalidStateError',
  3435. 'Can not call createAnswer after close'));
  3436. }
  3437. if (!(pc.signalingState === 'have-remote-offer' ||
  3438. pc.signalingState === 'have-local-pranswer')) {
  3439. return Promise.reject(makeError('InvalidStateError',
  3440. 'Can not call createAnswer in signalingState ' + pc.signalingState));
  3441. }
  3442. var sdp$1 = sdp.writeSessionBoilerplate(pc._sdpSessionId,
  3443. pc._sdpSessionVersion++);
  3444. if (pc.usingBundle) {
  3445. sdp$1 += 'a=group:BUNDLE ' + pc.transceivers.map(function(t) {
  3446. return t.mid;
  3447. }).join(' ') + '\r\n';
  3448. }
  3449. sdp$1 += 'a=ice-options:trickle\r\n';
  3450. var mediaSectionsInOffer = sdp.getMediaSections(
  3451. pc._remoteDescription.sdp).length;
  3452. pc.transceivers.forEach(function(transceiver, sdpMLineIndex) {
  3453. if (sdpMLineIndex + 1 > mediaSectionsInOffer) {
  3454. return;
  3455. }
  3456. if (transceiver.rejected) {
  3457. if (transceiver.kind === 'application') {
  3458. if (transceiver.protocol === 'DTLS/SCTP') { // legacy fmt
  3459. sdp$1 += 'm=application 0 DTLS/SCTP 5000\r\n';
  3460. } else {
  3461. sdp$1 += 'm=application 0 ' + transceiver.protocol +
  3462. ' webrtc-datachannel\r\n';
  3463. }
  3464. } else if (transceiver.kind === 'audio') {
  3465. sdp$1 += 'm=audio 0 UDP/TLS/RTP/SAVPF 0\r\n' +
  3466. 'a=rtpmap:0 PCMU/8000\r\n';
  3467. } else if (transceiver.kind === 'video') {
  3468. sdp$1 += 'm=video 0 UDP/TLS/RTP/SAVPF 120\r\n' +
  3469. 'a=rtpmap:120 VP8/90000\r\n';
  3470. }
  3471. sdp$1 += 'c=IN IP4 0.0.0.0\r\n' +
  3472. 'a=inactive\r\n' +
  3473. 'a=mid:' + transceiver.mid + '\r\n';
  3474. return;
  3475. }
  3476. // FIXME: look at direction.
  3477. if (transceiver.stream) {
  3478. var localTrack;
  3479. if (transceiver.kind === 'audio') {
  3480. localTrack = transceiver.stream.getAudioTracks()[0];
  3481. } else if (transceiver.kind === 'video') {
  3482. localTrack = transceiver.stream.getVideoTracks()[0];
  3483. }
  3484. if (localTrack) {
  3485. // add RTX
  3486. if (edgeVersion >= 15019 && transceiver.kind === 'video' &&
  3487. !transceiver.sendEncodingParameters[0].rtx) {
  3488. transceiver.sendEncodingParameters[0].rtx = {
  3489. ssrc: transceiver.sendEncodingParameters[0].ssrc + 1
  3490. };
  3491. }
  3492. }
  3493. }
  3494. // Calculate intersection of capabilities.
  3495. var commonCapabilities = getCommonCapabilities(
  3496. transceiver.localCapabilities,
  3497. transceiver.remoteCapabilities);
  3498. var hasRtx = commonCapabilities.codecs.filter(function(c) {
  3499. return c.name.toLowerCase() === 'rtx';
  3500. }).length;
  3501. if (!hasRtx && transceiver.sendEncodingParameters[0].rtx) {
  3502. delete transceiver.sendEncodingParameters[0].rtx;
  3503. }
  3504. sdp$1 += writeMediaSection(transceiver, commonCapabilities,
  3505. 'answer', transceiver.stream, pc._dtlsRole);
  3506. if (transceiver.rtcpParameters &&
  3507. transceiver.rtcpParameters.reducedSize) {
  3508. sdp$1 += 'a=rtcp-rsize\r\n';
  3509. }
  3510. });
  3511. var desc = new window.RTCSessionDescription({
  3512. type: 'answer',
  3513. sdp: sdp$1
  3514. });
  3515. return Promise.resolve(desc);
  3516. };
  3517. RTCPeerConnection.prototype.addIceCandidate = function(candidate) {
  3518. var pc = this;
  3519. var sections;
  3520. if (candidate && !(candidate.sdpMLineIndex !== undefined ||
  3521. candidate.sdpMid)) {
  3522. return Promise.reject(new TypeError('sdpMLineIndex or sdpMid required'));
  3523. }
  3524. // TODO: needs to go into ops queue.
  3525. return new Promise(function(resolve, reject) {
  3526. if (!pc._remoteDescription) {
  3527. return reject(makeError('InvalidStateError',
  3528. 'Can not add ICE candidate without a remote description'));
  3529. } else if (!candidate || candidate.candidate === '') {
  3530. for (var j = 0; j < pc.transceivers.length; j++) {
  3531. if (pc.transceivers[j].rejected) {
  3532. continue;
  3533. }
  3534. pc.transceivers[j].iceTransport.addRemoteCandidate({});
  3535. sections = sdp.getMediaSections(pc._remoteDescription.sdp);
  3536. sections[j] += 'a=end-of-candidates\r\n';
  3537. pc._remoteDescription.sdp =
  3538. sdp.getDescription(pc._remoteDescription.sdp) +
  3539. sections.join('');
  3540. if (pc.usingBundle) {
  3541. break;
  3542. }
  3543. }
  3544. } else {
  3545. var sdpMLineIndex = candidate.sdpMLineIndex;
  3546. if (candidate.sdpMid) {
  3547. for (var i = 0; i < pc.transceivers.length; i++) {
  3548. if (pc.transceivers[i].mid === candidate.sdpMid) {
  3549. sdpMLineIndex = i;
  3550. break;
  3551. }
  3552. }
  3553. }
  3554. var transceiver = pc.transceivers[sdpMLineIndex];
  3555. if (transceiver) {
  3556. if (transceiver.rejected) {
  3557. return resolve();
  3558. }
  3559. var cand = Object.keys(candidate.candidate).length > 0 ?
  3560. sdp.parseCandidate(candidate.candidate) : {};
  3561. // Ignore Chrome's invalid candidates since Edge does not like them.
  3562. if (cand.protocol === 'tcp' && (cand.port === 0 || cand.port === 9)) {
  3563. return resolve();
  3564. }
  3565. // Ignore RTCP candidates, we assume RTCP-MUX.
  3566. if (cand.component && cand.component !== 1) {
  3567. return resolve();
  3568. }
  3569. // when using bundle, avoid adding candidates to the wrong
  3570. // ice transport. And avoid adding candidates added in the SDP.
  3571. if (sdpMLineIndex === 0 || (sdpMLineIndex > 0 &&
  3572. transceiver.iceTransport !== pc.transceivers[0].iceTransport)) {
  3573. if (!maybeAddCandidate(transceiver.iceTransport, cand)) {
  3574. return reject(makeError('OperationError',
  3575. 'Can not add ICE candidate'));
  3576. }
  3577. }
  3578. // update the remoteDescription.
  3579. var candidateString = candidate.candidate.trim();
  3580. if (candidateString.indexOf('a=') === 0) {
  3581. candidateString = candidateString.substr(2);
  3582. }
  3583. sections = sdp.getMediaSections(pc._remoteDescription.sdp);
  3584. sections[sdpMLineIndex] += 'a=' +
  3585. (cand.type ? candidateString : 'end-of-candidates')
  3586. + '\r\n';
  3587. pc._remoteDescription.sdp =
  3588. sdp.getDescription(pc._remoteDescription.sdp) +
  3589. sections.join('');
  3590. } else {
  3591. return reject(makeError('OperationError',
  3592. 'Can not add ICE candidate'));
  3593. }
  3594. }
  3595. resolve();
  3596. });
  3597. };
  3598. RTCPeerConnection.prototype.getStats = function(selector) {
  3599. if (selector && selector instanceof window.MediaStreamTrack) {
  3600. var senderOrReceiver = null;
  3601. this.transceivers.forEach(function(transceiver) {
  3602. if (transceiver.rtpSender &&
  3603. transceiver.rtpSender.track === selector) {
  3604. senderOrReceiver = transceiver.rtpSender;
  3605. } else if (transceiver.rtpReceiver &&
  3606. transceiver.rtpReceiver.track === selector) {
  3607. senderOrReceiver = transceiver.rtpReceiver;
  3608. }
  3609. });
  3610. if (!senderOrReceiver) {
  3611. throw makeError('InvalidAccessError', 'Invalid selector.');
  3612. }
  3613. return senderOrReceiver.getStats();
  3614. }
  3615. var promises = [];
  3616. this.transceivers.forEach(function(transceiver) {
  3617. ['rtpSender', 'rtpReceiver', 'iceGatherer', 'iceTransport',
  3618. 'dtlsTransport'].forEach(function(method) {
  3619. if (transceiver[method]) {
  3620. promises.push(transceiver[method].getStats());
  3621. }
  3622. });
  3623. });
  3624. return Promise.all(promises).then(function(allStats) {
  3625. var results = new Map();
  3626. allStats.forEach(function(stats) {
  3627. stats.forEach(function(stat) {
  3628. results.set(stat.id, stat);
  3629. });
  3630. });
  3631. return results;
  3632. });
  3633. };
  3634. // fix low-level stat names and return Map instead of object.
  3635. var ortcObjects = ['RTCRtpSender', 'RTCRtpReceiver', 'RTCIceGatherer',
  3636. 'RTCIceTransport', 'RTCDtlsTransport'];
  3637. ortcObjects.forEach(function(ortcObjectName) {
  3638. var obj = window[ortcObjectName];
  3639. if (obj && obj.prototype && obj.prototype.getStats) {
  3640. var nativeGetstats = obj.prototype.getStats;
  3641. obj.prototype.getStats = function() {
  3642. return nativeGetstats.apply(this)
  3643. .then(function(nativeStats) {
  3644. var mapStats = new Map();
  3645. Object.keys(nativeStats).forEach(function(id) {
  3646. nativeStats[id].type = fixStatsType(nativeStats[id]);
  3647. mapStats.set(id, nativeStats[id]);
  3648. });
  3649. return mapStats;
  3650. });
  3651. };
  3652. }
  3653. });
  3654. // legacy callback shims. Should be moved to adapter.js some days.
  3655. var methods = ['createOffer', 'createAnswer'];
  3656. methods.forEach(function(method) {
  3657. var nativeMethod = RTCPeerConnection.prototype[method];
  3658. RTCPeerConnection.prototype[method] = function() {
  3659. var args = arguments;
  3660. if (typeof args[0] === 'function' ||
  3661. typeof args[1] === 'function') { // legacy
  3662. return nativeMethod.apply(this, [arguments[2]])
  3663. .then(function(description) {
  3664. if (typeof args[0] === 'function') {
  3665. args[0].apply(null, [description]);
  3666. }
  3667. }, function(error) {
  3668. if (typeof args[1] === 'function') {
  3669. args[1].apply(null, [error]);
  3670. }
  3671. });
  3672. }
  3673. return nativeMethod.apply(this, arguments);
  3674. };
  3675. });
  3676. methods = ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate'];
  3677. methods.forEach(function(method) {
  3678. var nativeMethod = RTCPeerConnection.prototype[method];
  3679. RTCPeerConnection.prototype[method] = function() {
  3680. var args = arguments;
  3681. if (typeof args[1] === 'function' ||
  3682. typeof args[2] === 'function') { // legacy
  3683. return nativeMethod.apply(this, arguments)
  3684. .then(function() {
  3685. if (typeof args[1] === 'function') {
  3686. args[1].apply(null);
  3687. }
  3688. }, function(error) {
  3689. if (typeof args[2] === 'function') {
  3690. args[2].apply(null, [error]);
  3691. }
  3692. });
  3693. }
  3694. return nativeMethod.apply(this, arguments);
  3695. };
  3696. });
  3697. // getStats is special. It doesn't have a spec legacy method yet we support
  3698. // getStats(something, cb) without error callbacks.
  3699. ['getStats'].forEach(function(method) {
  3700. var nativeMethod = RTCPeerConnection.prototype[method];
  3701. RTCPeerConnection.prototype[method] = function() {
  3702. var args = arguments;
  3703. if (typeof args[1] === 'function') {
  3704. return nativeMethod.apply(this, arguments)
  3705. .then(function() {
  3706. if (typeof args[1] === 'function') {
  3707. args[1].apply(null);
  3708. }
  3709. });
  3710. }
  3711. return nativeMethod.apply(this, arguments);
  3712. };
  3713. });
  3714. return RTCPeerConnection;
  3715. };
  3716. /*
  3717. * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
  3718. *
  3719. * Use of this source code is governed by a BSD-style license
  3720. * that can be found in the LICENSE file in the root of the source
  3721. * tree.
  3722. */
  3723. function shimGetUserMedia$2(window) {
  3724. const navigator = window && window.navigator;
  3725. const shimError_ = function(e) {
  3726. return {
  3727. name: {PermissionDeniedError: 'NotAllowedError'}[e.name] || e.name,
  3728. message: e.message,
  3729. constraint: e.constraint,
  3730. toString() {
  3731. return this.name;
  3732. }
  3733. };
  3734. };
  3735. // getUserMedia error shim.
  3736. const origGetUserMedia = navigator.mediaDevices.getUserMedia.
  3737. bind(navigator.mediaDevices);
  3738. navigator.mediaDevices.getUserMedia = function(c) {
  3739. return origGetUserMedia(c).catch(e => Promise.reject(shimError_(e)));
  3740. };
  3741. }
  3742. /*
  3743. * Copyright (c) 2018 The adapter.js project authors. All Rights Reserved.
  3744. *
  3745. * Use of this source code is governed by a BSD-style license
  3746. * that can be found in the LICENSE file in the root of the source
  3747. * tree.
  3748. */
  3749. function shimGetDisplayMedia$1(window) {
  3750. if (!('getDisplayMedia' in window.navigator)) {
  3751. return;
  3752. }
  3753. if (!(window.navigator.mediaDevices)) {
  3754. return;
  3755. }
  3756. if (window.navigator.mediaDevices &&
  3757. 'getDisplayMedia' in window.navigator.mediaDevices) {
  3758. return;
  3759. }
  3760. window.navigator.mediaDevices.getDisplayMedia =
  3761. window.navigator.getDisplayMedia.bind(window.navigator);
  3762. }
  3763. /*
  3764. * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
  3765. *
  3766. * Use of this source code is governed by a BSD-style license
  3767. * that can be found in the LICENSE file in the root of the source
  3768. * tree.
  3769. */
  3770. function shimPeerConnection$1(window, browserDetails) {
  3771. if (window.RTCIceGatherer) {
  3772. if (!window.RTCIceCandidate) {
  3773. window.RTCIceCandidate = function RTCIceCandidate(args) {
  3774. return args;
  3775. };
  3776. }
  3777. if (!window.RTCSessionDescription) {
  3778. window.RTCSessionDescription = function RTCSessionDescription(args) {
  3779. return args;
  3780. };
  3781. }
  3782. // this adds an additional event listener to MediaStrackTrack that signals
  3783. // when a tracks enabled property was changed. Workaround for a bug in
  3784. // addStream, see below. No longer required in 15025+
  3785. if (browserDetails.version < 15025) {
  3786. const origMSTEnabled = Object.getOwnPropertyDescriptor(
  3787. window.MediaStreamTrack.prototype, 'enabled');
  3788. Object.defineProperty(window.MediaStreamTrack.prototype, 'enabled', {
  3789. set(value) {
  3790. origMSTEnabled.set.call(this, value);
  3791. const ev = new Event('enabled');
  3792. ev.enabled = value;
  3793. this.dispatchEvent(ev);
  3794. }
  3795. });
  3796. }
  3797. }
  3798. // ORTC defines the DTMF sender a bit different.
  3799. // https://github.com/w3c/ortc/issues/714
  3800. if (window.RTCRtpSender && !('dtmf' in window.RTCRtpSender.prototype)) {
  3801. Object.defineProperty(window.RTCRtpSender.prototype, 'dtmf', {
  3802. get() {
  3803. if (this._dtmf === undefined) {
  3804. if (this.track.kind === 'audio') {
  3805. this._dtmf = new window.RTCDtmfSender(this);
  3806. } else if (this.track.kind === 'video') {
  3807. this._dtmf = null;
  3808. }
  3809. }
  3810. return this._dtmf;
  3811. }
  3812. });
  3813. }
  3814. // Edge currently only implements the RTCDtmfSender, not the
  3815. // RTCDTMFSender alias. See http://draft.ortc.org/#rtcdtmfsender2*
  3816. if (window.RTCDtmfSender && !window.RTCDTMFSender) {
  3817. window.RTCDTMFSender = window.RTCDtmfSender;
  3818. }
  3819. const RTCPeerConnectionShim = rtcpeerconnection(window,
  3820. browserDetails.version);
  3821. window.RTCPeerConnection = function RTCPeerConnection(config) {
  3822. if (config && config.iceServers) {
  3823. config.iceServers = filterIceServers$1(config.iceServers,
  3824. browserDetails.version);
  3825. log$1('ICE servers after filtering:', config.iceServers);
  3826. }
  3827. return new RTCPeerConnectionShim(config);
  3828. };
  3829. window.RTCPeerConnection.prototype = RTCPeerConnectionShim.prototype;
  3830. }
  3831. function shimReplaceTrack(window) {
  3832. // ORTC has replaceTrack -- https://github.com/w3c/ortc/issues/614
  3833. if (window.RTCRtpSender &&
  3834. !('replaceTrack' in window.RTCRtpSender.prototype)) {
  3835. window.RTCRtpSender.prototype.replaceTrack =
  3836. window.RTCRtpSender.prototype.setTrack;
  3837. }
  3838. }
  3839. var edgeShim = /*#__PURE__*/Object.freeze({
  3840. __proto__: null,
  3841. shimPeerConnection: shimPeerConnection$1,
  3842. shimReplaceTrack: shimReplaceTrack,
  3843. shimGetUserMedia: shimGetUserMedia$2,
  3844. shimGetDisplayMedia: shimGetDisplayMedia$1
  3845. });
  3846. /*
  3847. * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
  3848. *
  3849. * Use of this source code is governed by a BSD-style license
  3850. * that can be found in the LICENSE file in the root of the source
  3851. * tree.
  3852. */
  3853. function shimGetUserMedia$1(window, browserDetails) {
  3854. const navigator = window && window.navigator;
  3855. const MediaStreamTrack = window && window.MediaStreamTrack;
  3856. navigator.getUserMedia = function(constraints, onSuccess, onError) {
  3857. // Replace Firefox 44+'s deprecation warning with unprefixed version.
  3858. deprecated('navigator.getUserMedia',
  3859. 'navigator.mediaDevices.getUserMedia');
  3860. navigator.mediaDevices.getUserMedia(constraints).then(onSuccess, onError);
  3861. };
  3862. if (!(browserDetails.version > 55 &&
  3863. 'autoGainControl' in navigator.mediaDevices.getSupportedConstraints())) {
  3864. const remap = function(obj, a, b) {
  3865. if (a in obj && !(b in obj)) {
  3866. obj[b] = obj[a];
  3867. delete obj[a];
  3868. }
  3869. };
  3870. const nativeGetUserMedia = navigator.mediaDevices.getUserMedia.
  3871. bind(navigator.mediaDevices);
  3872. navigator.mediaDevices.getUserMedia = function(c) {
  3873. if (typeof c === 'object' && typeof c.audio === 'object') {
  3874. c = JSON.parse(JSON.stringify(c));
  3875. remap(c.audio, 'autoGainControl', 'mozAutoGainControl');
  3876. remap(c.audio, 'noiseSuppression', 'mozNoiseSuppression');
  3877. }
  3878. return nativeGetUserMedia(c);
  3879. };
  3880. if (MediaStreamTrack && MediaStreamTrack.prototype.getSettings) {
  3881. const nativeGetSettings = MediaStreamTrack.prototype.getSettings;
  3882. MediaStreamTrack.prototype.getSettings = function() {
  3883. const obj = nativeGetSettings.apply(this, arguments);
  3884. remap(obj, 'mozAutoGainControl', 'autoGainControl');
  3885. remap(obj, 'mozNoiseSuppression', 'noiseSuppression');
  3886. return obj;
  3887. };
  3888. }
  3889. if (MediaStreamTrack && MediaStreamTrack.prototype.applyConstraints) {
  3890. const nativeApplyConstraints =
  3891. MediaStreamTrack.prototype.applyConstraints;
  3892. MediaStreamTrack.prototype.applyConstraints = function(c) {
  3893. if (this.kind === 'audio' && typeof c === 'object') {
  3894. c = JSON.parse(JSON.stringify(c));
  3895. remap(c, 'autoGainControl', 'mozAutoGainControl');
  3896. remap(c, 'noiseSuppression', 'mozNoiseSuppression');
  3897. }
  3898. return nativeApplyConstraints.apply(this, [c]);
  3899. };
  3900. }
  3901. }
  3902. }
  3903. /*
  3904. * Copyright (c) 2018 The adapter.js project authors. All Rights Reserved.
  3905. *
  3906. * Use of this source code is governed by a BSD-style license
  3907. * that can be found in the LICENSE file in the root of the source
  3908. * tree.
  3909. */
  3910. function shimGetDisplayMedia(window, preferredMediaSource) {
  3911. if (window.navigator.mediaDevices &&
  3912. 'getDisplayMedia' in window.navigator.mediaDevices) {
  3913. return;
  3914. }
  3915. if (!(window.navigator.mediaDevices)) {
  3916. return;
  3917. }
  3918. window.navigator.mediaDevices.getDisplayMedia =
  3919. function getDisplayMedia(constraints) {
  3920. if (!(constraints && constraints.video)) {
  3921. const err = new DOMException('getDisplayMedia without video ' +
  3922. 'constraints is undefined');
  3923. err.name = 'NotFoundError';
  3924. // from https://heycam.github.io/webidl/#idl-DOMException-error-names
  3925. err.code = 8;
  3926. return Promise.reject(err);
  3927. }
  3928. if (constraints.video === true) {
  3929. constraints.video = {mediaSource: preferredMediaSource};
  3930. } else {
  3931. constraints.video.mediaSource = preferredMediaSource;
  3932. }
  3933. return window.navigator.mediaDevices.getUserMedia(constraints);
  3934. };
  3935. }
  3936. /*
  3937. * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
  3938. *
  3939. * Use of this source code is governed by a BSD-style license
  3940. * that can be found in the LICENSE file in the root of the source
  3941. * tree.
  3942. */
  3943. function shimOnTrack(window) {
  3944. if (typeof window === 'object' && window.RTCTrackEvent &&
  3945. ('receiver' in window.RTCTrackEvent.prototype) &&
  3946. !('transceiver' in window.RTCTrackEvent.prototype)) {
  3947. Object.defineProperty(window.RTCTrackEvent.prototype, 'transceiver', {
  3948. get() {
  3949. return {receiver: this.receiver};
  3950. }
  3951. });
  3952. }
  3953. }
  3954. function shimPeerConnection(window, browserDetails) {
  3955. if (typeof window !== 'object' ||
  3956. !(window.RTCPeerConnection || window.mozRTCPeerConnection)) {
  3957. return; // probably media.peerconnection.enabled=false in about:config
  3958. }
  3959. if (!window.RTCPeerConnection && window.mozRTCPeerConnection) {
  3960. // very basic support for old versions.
  3961. window.RTCPeerConnection = window.mozRTCPeerConnection;
  3962. }
  3963. if (browserDetails.version < 53) {
  3964. // shim away need for obsolete RTCIceCandidate/RTCSessionDescription.
  3965. ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate']
  3966. .forEach(function(method) {
  3967. const nativeMethod = window.RTCPeerConnection.prototype[method];
  3968. const methodObj = {[method]() {
  3969. arguments[0] = new ((method === 'addIceCandidate') ?
  3970. window.RTCIceCandidate :
  3971. window.RTCSessionDescription)(arguments[0]);
  3972. return nativeMethod.apply(this, arguments);
  3973. }};
  3974. window.RTCPeerConnection.prototype[method] = methodObj[method];
  3975. });
  3976. }
  3977. const modernStatsTypes = {
  3978. inboundrtp: 'inbound-rtp',
  3979. outboundrtp: 'outbound-rtp',
  3980. candidatepair: 'candidate-pair',
  3981. localcandidate: 'local-candidate',
  3982. remotecandidate: 'remote-candidate'
  3983. };
  3984. const nativeGetStats = window.RTCPeerConnection.prototype.getStats;
  3985. window.RTCPeerConnection.prototype.getStats = function getStats() {
  3986. const [selector, onSucc, onErr] = arguments;
  3987. return nativeGetStats.apply(this, [selector || null])
  3988. .then(stats => {
  3989. if (browserDetails.version < 53 && !onSucc) {
  3990. // Shim only promise getStats with spec-hyphens in type names
  3991. // Leave callback version alone; misc old uses of forEach before Map
  3992. try {
  3993. stats.forEach(stat => {
  3994. stat.type = modernStatsTypes[stat.type] || stat.type;
  3995. });
  3996. } catch (e) {
  3997. if (e.name !== 'TypeError') {
  3998. throw e;
  3999. }
  4000. // Avoid TypeError: "type" is read-only, in old versions. 34-43ish
  4001. stats.forEach((stat, i) => {
  4002. stats.set(i, Object.assign({}, stat, {
  4003. type: modernStatsTypes[stat.type] || stat.type
  4004. }));
  4005. });
  4006. }
  4007. }
  4008. return stats;
  4009. })
  4010. .then(onSucc, onErr);
  4011. };
  4012. }
  4013. function shimSenderGetStats(window) {
  4014. if (!(typeof window === 'object' && window.RTCPeerConnection &&
  4015. window.RTCRtpSender)) {
  4016. return;
  4017. }
  4018. if (window.RTCRtpSender && 'getStats' in window.RTCRtpSender.prototype) {
  4019. return;
  4020. }
  4021. const origGetSenders = window.RTCPeerConnection.prototype.getSenders;
  4022. if (origGetSenders) {
  4023. window.RTCPeerConnection.prototype.getSenders = function getSenders() {
  4024. const senders = origGetSenders.apply(this, []);
  4025. senders.forEach(sender => sender._pc = this);
  4026. return senders;
  4027. };
  4028. }
  4029. const origAddTrack = window.RTCPeerConnection.prototype.addTrack;
  4030. if (origAddTrack) {
  4031. window.RTCPeerConnection.prototype.addTrack = function addTrack() {
  4032. const sender = origAddTrack.apply(this, arguments);
  4033. sender._pc = this;
  4034. return sender;
  4035. };
  4036. }
  4037. window.RTCRtpSender.prototype.getStats = function getStats() {
  4038. return this.track ? this._pc.getStats(this.track) :
  4039. Promise.resolve(new Map());
  4040. };
  4041. }
  4042. function shimReceiverGetStats(window) {
  4043. if (!(typeof window === 'object' && window.RTCPeerConnection &&
  4044. window.RTCRtpSender)) {
  4045. return;
  4046. }
  4047. if (window.RTCRtpSender && 'getStats' in window.RTCRtpReceiver.prototype) {
  4048. return;
  4049. }
  4050. const origGetReceivers = window.RTCPeerConnection.prototype.getReceivers;
  4051. if (origGetReceivers) {
  4052. window.RTCPeerConnection.prototype.getReceivers = function getReceivers() {
  4053. const receivers = origGetReceivers.apply(this, []);
  4054. receivers.forEach(receiver => receiver._pc = this);
  4055. return receivers;
  4056. };
  4057. }
  4058. wrapPeerConnectionEvent(window, 'track', e => {
  4059. e.receiver._pc = e.srcElement;
  4060. return e;
  4061. });
  4062. window.RTCRtpReceiver.prototype.getStats = function getStats() {
  4063. return this._pc.getStats(this.track);
  4064. };
  4065. }
  4066. function shimRemoveStream(window) {
  4067. if (!window.RTCPeerConnection ||
  4068. 'removeStream' in window.RTCPeerConnection.prototype) {
  4069. return;
  4070. }
  4071. window.RTCPeerConnection.prototype.removeStream =
  4072. function removeStream(stream) {
  4073. deprecated('removeStream', 'removeTrack');
  4074. this.getSenders().forEach(sender => {
  4075. if (sender.track && stream.getTracks().includes(sender.track)) {
  4076. this.removeTrack(sender);
  4077. }
  4078. });
  4079. };
  4080. }
  4081. function shimRTCDataChannel(window) {
  4082. // rename DataChannel to RTCDataChannel (native fix in FF60):
  4083. // https://bugzilla.mozilla.org/show_bug.cgi?id=1173851
  4084. if (window.DataChannel && !window.RTCDataChannel) {
  4085. window.RTCDataChannel = window.DataChannel;
  4086. }
  4087. }
  4088. function shimAddTransceiver(window) {
  4089. // https://github.com/webrtcHacks/adapter/issues/998#issuecomment-516921647
  4090. // Firefox ignores the init sendEncodings options passed to addTransceiver
  4091. // https://bugzilla.mozilla.org/show_bug.cgi?id=1396918
  4092. if (!(typeof window === 'object' && window.RTCPeerConnection)) {
  4093. return;
  4094. }
  4095. const origAddTransceiver = window.RTCPeerConnection.prototype.addTransceiver;
  4096. if (origAddTransceiver) {
  4097. window.RTCPeerConnection.prototype.addTransceiver =
  4098. function addTransceiver() {
  4099. this.setParametersPromises = [];
  4100. const initParameters = arguments[1];
  4101. const shouldPerformCheck = initParameters &&
  4102. 'sendEncodings' in initParameters;
  4103. if (shouldPerformCheck) {
  4104. // If sendEncodings params are provided, validate grammar
  4105. initParameters.sendEncodings.forEach((encodingParam) => {
  4106. if ('rid' in encodingParam) {
  4107. const ridRegex = /^[a-z0-9]{0,16}$/i;
  4108. if (!ridRegex.test(encodingParam.rid)) {
  4109. throw new TypeError('Invalid RID value provided.');
  4110. }
  4111. }
  4112. if ('scaleResolutionDownBy' in encodingParam) {
  4113. if (!(parseFloat(encodingParam.scaleResolutionDownBy) >= 1.0)) {
  4114. throw new RangeError('scale_resolution_down_by must be >= 1.0');
  4115. }
  4116. }
  4117. if ('maxFramerate' in encodingParam) {
  4118. if (!(parseFloat(encodingParam.maxFramerate) >= 0)) {
  4119. throw new RangeError('max_framerate must be >= 0.0');
  4120. }
  4121. }
  4122. });
  4123. }
  4124. const transceiver = origAddTransceiver.apply(this, arguments);
  4125. if (shouldPerformCheck) {
  4126. // Check if the init options were applied. If not we do this in an
  4127. // asynchronous way and save the promise reference in a global object.
  4128. // This is an ugly hack, but at the same time is way more robust than
  4129. // checking the sender parameters before and after the createOffer
  4130. // Also note that after the createoffer we are not 100% sure that
  4131. // the params were asynchronously applied so we might miss the
  4132. // opportunity to recreate offer.
  4133. const {sender} = transceiver;
  4134. const params = sender.getParameters();
  4135. if (!('encodings' in params) ||
  4136. // Avoid being fooled by patched getParameters() below.
  4137. (params.encodings.length === 1 &&
  4138. Object.keys(params.encodings[0]).length === 0)) {
  4139. params.encodings = initParameters.sendEncodings;
  4140. sender.sendEncodings = initParameters.sendEncodings;
  4141. this.setParametersPromises.push(sender.setParameters(params)
  4142. .then(() => {
  4143. delete sender.sendEncodings;
  4144. }).catch(() => {
  4145. delete sender.sendEncodings;
  4146. })
  4147. );
  4148. }
  4149. }
  4150. return transceiver;
  4151. };
  4152. }
  4153. }
  4154. function shimGetParameters(window) {
  4155. if (!(typeof window === 'object' && window.RTCRtpSender)) {
  4156. return;
  4157. }
  4158. const origGetParameters = window.RTCRtpSender.prototype.getParameters;
  4159. if (origGetParameters) {
  4160. window.RTCRtpSender.prototype.getParameters =
  4161. function getParameters() {
  4162. const params = origGetParameters.apply(this, arguments);
  4163. if (!('encodings' in params)) {
  4164. params.encodings = [].concat(this.sendEncodings || [{}]);
  4165. }
  4166. return params;
  4167. };
  4168. }
  4169. }
  4170. function shimCreateOffer(window) {
  4171. // https://github.com/webrtcHacks/adapter/issues/998#issuecomment-516921647
  4172. // Firefox ignores the init sendEncodings options passed to addTransceiver
  4173. // https://bugzilla.mozilla.org/show_bug.cgi?id=1396918
  4174. if (!(typeof window === 'object' && window.RTCPeerConnection)) {
  4175. return;
  4176. }
  4177. const origCreateOffer = window.RTCPeerConnection.prototype.createOffer;
  4178. window.RTCPeerConnection.prototype.createOffer = function createOffer() {
  4179. if (this.setParametersPromises && this.setParametersPromises.length) {
  4180. return Promise.all(this.setParametersPromises)
  4181. .then(() => {
  4182. return origCreateOffer.apply(this, arguments);
  4183. })
  4184. .finally(() => {
  4185. this.setParametersPromises = [];
  4186. });
  4187. }
  4188. return origCreateOffer.apply(this, arguments);
  4189. };
  4190. }
  4191. function shimCreateAnswer(window) {
  4192. // https://github.com/webrtcHacks/adapter/issues/998#issuecomment-516921647
  4193. // Firefox ignores the init sendEncodings options passed to addTransceiver
  4194. // https://bugzilla.mozilla.org/show_bug.cgi?id=1396918
  4195. if (!(typeof window === 'object' && window.RTCPeerConnection)) {
  4196. return;
  4197. }
  4198. const origCreateAnswer = window.RTCPeerConnection.prototype.createAnswer;
  4199. window.RTCPeerConnection.prototype.createAnswer = function createAnswer() {
  4200. if (this.setParametersPromises && this.setParametersPromises.length) {
  4201. return Promise.all(this.setParametersPromises)
  4202. .then(() => {
  4203. return origCreateAnswer.apply(this, arguments);
  4204. })
  4205. .finally(() => {
  4206. this.setParametersPromises = [];
  4207. });
  4208. }
  4209. return origCreateAnswer.apply(this, arguments);
  4210. };
  4211. }
  4212. var firefoxShim = /*#__PURE__*/Object.freeze({
  4213. __proto__: null,
  4214. shimOnTrack: shimOnTrack,
  4215. shimPeerConnection: shimPeerConnection,
  4216. shimSenderGetStats: shimSenderGetStats,
  4217. shimReceiverGetStats: shimReceiverGetStats,
  4218. shimRemoveStream: shimRemoveStream,
  4219. shimRTCDataChannel: shimRTCDataChannel,
  4220. shimAddTransceiver: shimAddTransceiver,
  4221. shimGetParameters: shimGetParameters,
  4222. shimCreateOffer: shimCreateOffer,
  4223. shimCreateAnswer: shimCreateAnswer,
  4224. shimGetUserMedia: shimGetUserMedia$1,
  4225. shimGetDisplayMedia: shimGetDisplayMedia
  4226. });
  4227. /*
  4228. * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
  4229. *
  4230. * Use of this source code is governed by a BSD-style license
  4231. * that can be found in the LICENSE file in the root of the source
  4232. * tree.
  4233. */
  4234. function shimLocalStreamsAPI(window) {
  4235. if (typeof window !== 'object' || !window.RTCPeerConnection) {
  4236. return;
  4237. }
  4238. if (!('getLocalStreams' in window.RTCPeerConnection.prototype)) {
  4239. window.RTCPeerConnection.prototype.getLocalStreams =
  4240. function getLocalStreams() {
  4241. if (!this._localStreams) {
  4242. this._localStreams = [];
  4243. }
  4244. return this._localStreams;
  4245. };
  4246. }
  4247. if (!('addStream' in window.RTCPeerConnection.prototype)) {
  4248. const _addTrack = window.RTCPeerConnection.prototype.addTrack;
  4249. window.RTCPeerConnection.prototype.addStream = function addStream(stream) {
  4250. if (!this._localStreams) {
  4251. this._localStreams = [];
  4252. }
  4253. if (!this._localStreams.includes(stream)) {
  4254. this._localStreams.push(stream);
  4255. }
  4256. // Try to emulate Chrome's behaviour of adding in audio-video order.
  4257. // Safari orders by track id.
  4258. stream.getAudioTracks().forEach(track => _addTrack.call(this, track,
  4259. stream));
  4260. stream.getVideoTracks().forEach(track => _addTrack.call(this, track,
  4261. stream));
  4262. };
  4263. window.RTCPeerConnection.prototype.addTrack =
  4264. function addTrack(track, ...streams) {
  4265. if (streams) {
  4266. streams.forEach((stream) => {
  4267. if (!this._localStreams) {
  4268. this._localStreams = [stream];
  4269. } else if (!this._localStreams.includes(stream)) {
  4270. this._localStreams.push(stream);
  4271. }
  4272. });
  4273. }
  4274. return _addTrack.apply(this, arguments);
  4275. };
  4276. }
  4277. if (!('removeStream' in window.RTCPeerConnection.prototype)) {
  4278. window.RTCPeerConnection.prototype.removeStream =
  4279. function removeStream(stream) {
  4280. if (!this._localStreams) {
  4281. this._localStreams = [];
  4282. }
  4283. const index = this._localStreams.indexOf(stream);
  4284. if (index === -1) {
  4285. return;
  4286. }
  4287. this._localStreams.splice(index, 1);
  4288. const tracks = stream.getTracks();
  4289. this.getSenders().forEach(sender => {
  4290. if (tracks.includes(sender.track)) {
  4291. this.removeTrack(sender);
  4292. }
  4293. });
  4294. };
  4295. }
  4296. }
  4297. function shimRemoteStreamsAPI(window) {
  4298. if (typeof window !== 'object' || !window.RTCPeerConnection) {
  4299. return;
  4300. }
  4301. if (!('getRemoteStreams' in window.RTCPeerConnection.prototype)) {
  4302. window.RTCPeerConnection.prototype.getRemoteStreams =
  4303. function getRemoteStreams() {
  4304. return this._remoteStreams ? this._remoteStreams : [];
  4305. };
  4306. }
  4307. if (!('onaddstream' in window.RTCPeerConnection.prototype)) {
  4308. Object.defineProperty(window.RTCPeerConnection.prototype, 'onaddstream', {
  4309. get() {
  4310. return this._onaddstream;
  4311. },
  4312. set(f) {
  4313. if (this._onaddstream) {
  4314. this.removeEventListener('addstream', this._onaddstream);
  4315. this.removeEventListener('track', this._onaddstreampoly);
  4316. }
  4317. this.addEventListener('addstream', this._onaddstream = f);
  4318. this.addEventListener('track', this._onaddstreampoly = (e) => {
  4319. e.streams.forEach(stream => {
  4320. if (!this._remoteStreams) {
  4321. this._remoteStreams = [];
  4322. }
  4323. if (this._remoteStreams.includes(stream)) {
  4324. return;
  4325. }
  4326. this._remoteStreams.push(stream);
  4327. const event = new Event('addstream');
  4328. event.stream = stream;
  4329. this.dispatchEvent(event);
  4330. });
  4331. });
  4332. }
  4333. });
  4334. const origSetRemoteDescription =
  4335. window.RTCPeerConnection.prototype.setRemoteDescription;
  4336. window.RTCPeerConnection.prototype.setRemoteDescription =
  4337. function setRemoteDescription() {
  4338. const pc = this;
  4339. if (!this._onaddstreampoly) {
  4340. this.addEventListener('track', this._onaddstreampoly = function(e) {
  4341. e.streams.forEach(stream => {
  4342. if (!pc._remoteStreams) {
  4343. pc._remoteStreams = [];
  4344. }
  4345. if (pc._remoteStreams.indexOf(stream) >= 0) {
  4346. return;
  4347. }
  4348. pc._remoteStreams.push(stream);
  4349. const event = new Event('addstream');
  4350. event.stream = stream;
  4351. pc.dispatchEvent(event);
  4352. });
  4353. });
  4354. }
  4355. return origSetRemoteDescription.apply(pc, arguments);
  4356. };
  4357. }
  4358. }
  4359. function shimCallbacksAPI(window) {
  4360. if (typeof window !== 'object' || !window.RTCPeerConnection) {
  4361. return;
  4362. }
  4363. const prototype = window.RTCPeerConnection.prototype;
  4364. const origCreateOffer = prototype.createOffer;
  4365. const origCreateAnswer = prototype.createAnswer;
  4366. const setLocalDescription = prototype.setLocalDescription;
  4367. const setRemoteDescription = prototype.setRemoteDescription;
  4368. const addIceCandidate = prototype.addIceCandidate;
  4369. prototype.createOffer =
  4370. function createOffer(successCallback, failureCallback) {
  4371. const options = (arguments.length >= 2) ? arguments[2] : arguments[0];
  4372. const promise = origCreateOffer.apply(this, [options]);
  4373. if (!failureCallback) {
  4374. return promise;
  4375. }
  4376. promise.then(successCallback, failureCallback);
  4377. return Promise.resolve();
  4378. };
  4379. prototype.createAnswer =
  4380. function createAnswer(successCallback, failureCallback) {
  4381. const options = (arguments.length >= 2) ? arguments[2] : arguments[0];
  4382. const promise = origCreateAnswer.apply(this, [options]);
  4383. if (!failureCallback) {
  4384. return promise;
  4385. }
  4386. promise.then(successCallback, failureCallback);
  4387. return Promise.resolve();
  4388. };
  4389. let withCallback = function(description, successCallback, failureCallback) {
  4390. const promise = setLocalDescription.apply(this, [description]);
  4391. if (!failureCallback) {
  4392. return promise;
  4393. }
  4394. promise.then(successCallback, failureCallback);
  4395. return Promise.resolve();
  4396. };
  4397. prototype.setLocalDescription = withCallback;
  4398. withCallback = function(description, successCallback, failureCallback) {
  4399. const promise = setRemoteDescription.apply(this, [description]);
  4400. if (!failureCallback) {
  4401. return promise;
  4402. }
  4403. promise.then(successCallback, failureCallback);
  4404. return Promise.resolve();
  4405. };
  4406. prototype.setRemoteDescription = withCallback;
  4407. withCallback = function(candidate, successCallback, failureCallback) {
  4408. const promise = addIceCandidate.apply(this, [candidate]);
  4409. if (!failureCallback) {
  4410. return promise;
  4411. }
  4412. promise.then(successCallback, failureCallback);
  4413. return Promise.resolve();
  4414. };
  4415. prototype.addIceCandidate = withCallback;
  4416. }
  4417. function shimGetUserMedia(window) {
  4418. const navigator = window && window.navigator;
  4419. if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
  4420. // shim not needed in Safari 12.1
  4421. const mediaDevices = navigator.mediaDevices;
  4422. const _getUserMedia = mediaDevices.getUserMedia.bind(mediaDevices);
  4423. navigator.mediaDevices.getUserMedia = (constraints) => {
  4424. return _getUserMedia(shimConstraints(constraints));
  4425. };
  4426. }
  4427. if (!navigator.getUserMedia && navigator.mediaDevices &&
  4428. navigator.mediaDevices.getUserMedia) {
  4429. navigator.getUserMedia = function getUserMedia(constraints, cb, errcb) {
  4430. navigator.mediaDevices.getUserMedia(constraints)
  4431. .then(cb, errcb);
  4432. }.bind(navigator);
  4433. }
  4434. }
  4435. function shimConstraints(constraints) {
  4436. if (constraints && constraints.video !== undefined) {
  4437. return Object.assign({},
  4438. constraints,
  4439. {video: compactObject(constraints.video)}
  4440. );
  4441. }
  4442. return constraints;
  4443. }
  4444. function shimRTCIceServerUrls(window) {
  4445. if (!window.RTCPeerConnection) {
  4446. return;
  4447. }
  4448. // migrate from non-spec RTCIceServer.url to RTCIceServer.urls
  4449. const OrigPeerConnection = window.RTCPeerConnection;
  4450. window.RTCPeerConnection =
  4451. function RTCPeerConnection(pcConfig, pcConstraints) {
  4452. if (pcConfig && pcConfig.iceServers) {
  4453. const newIceServers = [];
  4454. for (let i = 0; i < pcConfig.iceServers.length; i++) {
  4455. let server = pcConfig.iceServers[i];
  4456. if (!server.hasOwnProperty('urls') &&
  4457. server.hasOwnProperty('url')) {
  4458. deprecated('RTCIceServer.url', 'RTCIceServer.urls');
  4459. server = JSON.parse(JSON.stringify(server));
  4460. server.urls = server.url;
  4461. delete server.url;
  4462. newIceServers.push(server);
  4463. } else {
  4464. newIceServers.push(pcConfig.iceServers[i]);
  4465. }
  4466. }
  4467. pcConfig.iceServers = newIceServers;
  4468. }
  4469. return new OrigPeerConnection(pcConfig, pcConstraints);
  4470. };
  4471. window.RTCPeerConnection.prototype = OrigPeerConnection.prototype;
  4472. // wrap static methods. Currently just generateCertificate.
  4473. if ('generateCertificate' in OrigPeerConnection) {
  4474. Object.defineProperty(window.RTCPeerConnection, 'generateCertificate', {
  4475. get() {
  4476. return OrigPeerConnection.generateCertificate;
  4477. }
  4478. });
  4479. }
  4480. }
  4481. function shimTrackEventTransceiver(window) {
  4482. // Add event.transceiver member over deprecated event.receiver
  4483. if (typeof window === 'object' && window.RTCTrackEvent &&
  4484. 'receiver' in window.RTCTrackEvent.prototype &&
  4485. !('transceiver' in window.RTCTrackEvent.prototype)) {
  4486. Object.defineProperty(window.RTCTrackEvent.prototype, 'transceiver', {
  4487. get() {
  4488. return {receiver: this.receiver};
  4489. }
  4490. });
  4491. }
  4492. }
  4493. function shimCreateOfferLegacy(window) {
  4494. const origCreateOffer = window.RTCPeerConnection.prototype.createOffer;
  4495. window.RTCPeerConnection.prototype.createOffer =
  4496. function createOffer(offerOptions) {
  4497. if (offerOptions) {
  4498. if (typeof offerOptions.offerToReceiveAudio !== 'undefined') {
  4499. // support bit values
  4500. offerOptions.offerToReceiveAudio =
  4501. !!offerOptions.offerToReceiveAudio;
  4502. }
  4503. const audioTransceiver = this.getTransceivers().find(transceiver =>
  4504. transceiver.receiver.track.kind === 'audio');
  4505. if (offerOptions.offerToReceiveAudio === false && audioTransceiver) {
  4506. if (audioTransceiver.direction === 'sendrecv') {
  4507. if (audioTransceiver.setDirection) {
  4508. audioTransceiver.setDirection('sendonly');
  4509. } else {
  4510. audioTransceiver.direction = 'sendonly';
  4511. }
  4512. } else if (audioTransceiver.direction === 'recvonly') {
  4513. if (audioTransceiver.setDirection) {
  4514. audioTransceiver.setDirection('inactive');
  4515. } else {
  4516. audioTransceiver.direction = 'inactive';
  4517. }
  4518. }
  4519. } else if (offerOptions.offerToReceiveAudio === true &&
  4520. !audioTransceiver) {
  4521. this.addTransceiver('audio');
  4522. }
  4523. if (typeof offerOptions.offerToReceiveVideo !== 'undefined') {
  4524. // support bit values
  4525. offerOptions.offerToReceiveVideo =
  4526. !!offerOptions.offerToReceiveVideo;
  4527. }
  4528. const videoTransceiver = this.getTransceivers().find(transceiver =>
  4529. transceiver.receiver.track.kind === 'video');
  4530. if (offerOptions.offerToReceiveVideo === false && videoTransceiver) {
  4531. if (videoTransceiver.direction === 'sendrecv') {
  4532. if (videoTransceiver.setDirection) {
  4533. videoTransceiver.setDirection('sendonly');
  4534. } else {
  4535. videoTransceiver.direction = 'sendonly';
  4536. }
  4537. } else if (videoTransceiver.direction === 'recvonly') {
  4538. if (videoTransceiver.setDirection) {
  4539. videoTransceiver.setDirection('inactive');
  4540. } else {
  4541. videoTransceiver.direction = 'inactive';
  4542. }
  4543. }
  4544. } else if (offerOptions.offerToReceiveVideo === true &&
  4545. !videoTransceiver) {
  4546. this.addTransceiver('video');
  4547. }
  4548. }
  4549. return origCreateOffer.apply(this, arguments);
  4550. };
  4551. }
  4552. function shimAudioContext(window) {
  4553. if (typeof window !== 'object' || window.AudioContext) {
  4554. return;
  4555. }
  4556. window.AudioContext = window.webkitAudioContext;
  4557. }
  4558. var safariShim = /*#__PURE__*/Object.freeze({
  4559. __proto__: null,
  4560. shimLocalStreamsAPI: shimLocalStreamsAPI,
  4561. shimRemoteStreamsAPI: shimRemoteStreamsAPI,
  4562. shimCallbacksAPI: shimCallbacksAPI,
  4563. shimGetUserMedia: shimGetUserMedia,
  4564. shimConstraints: shimConstraints,
  4565. shimRTCIceServerUrls: shimRTCIceServerUrls,
  4566. shimTrackEventTransceiver: shimTrackEventTransceiver,
  4567. shimCreateOfferLegacy: shimCreateOfferLegacy,
  4568. shimAudioContext: shimAudioContext
  4569. });
  4570. /*
  4571. * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
  4572. *
  4573. * Use of this source code is governed by a BSD-style license
  4574. * that can be found in the LICENSE file in the root of the source
  4575. * tree.
  4576. */
  4577. function shimRTCIceCandidate(window) {
  4578. // foundation is arbitrarily chosen as an indicator for full support for
  4579. // https://w3c.github.io/webrtc-pc/#rtcicecandidate-interface
  4580. if (!window.RTCIceCandidate || (window.RTCIceCandidate && 'foundation' in
  4581. window.RTCIceCandidate.prototype)) {
  4582. return;
  4583. }
  4584. const NativeRTCIceCandidate = window.RTCIceCandidate;
  4585. window.RTCIceCandidate = function RTCIceCandidate(args) {
  4586. // Remove the a= which shouldn't be part of the candidate string.
  4587. if (typeof args === 'object' && args.candidate &&
  4588. args.candidate.indexOf('a=') === 0) {
  4589. args = JSON.parse(JSON.stringify(args));
  4590. args.candidate = args.candidate.substr(2);
  4591. }
  4592. if (args.candidate && args.candidate.length) {
  4593. // Augment the native candidate with the parsed fields.
  4594. const nativeCandidate = new NativeRTCIceCandidate(args);
  4595. const parsedCandidate = sdp.parseCandidate(args.candidate);
  4596. const augmentedCandidate = Object.assign(nativeCandidate,
  4597. parsedCandidate);
  4598. // Add a serializer that does not serialize the extra attributes.
  4599. augmentedCandidate.toJSON = function toJSON() {
  4600. return {
  4601. candidate: augmentedCandidate.candidate,
  4602. sdpMid: augmentedCandidate.sdpMid,
  4603. sdpMLineIndex: augmentedCandidate.sdpMLineIndex,
  4604. usernameFragment: augmentedCandidate.usernameFragment,
  4605. };
  4606. };
  4607. return augmentedCandidate;
  4608. }
  4609. return new NativeRTCIceCandidate(args);
  4610. };
  4611. window.RTCIceCandidate.prototype = NativeRTCIceCandidate.prototype;
  4612. // Hook up the augmented candidate in onicecandidate and
  4613. // addEventListener('icecandidate', ...)
  4614. wrapPeerConnectionEvent(window, 'icecandidate', e => {
  4615. if (e.candidate) {
  4616. Object.defineProperty(e, 'candidate', {
  4617. value: new window.RTCIceCandidate(e.candidate),
  4618. writable: 'false'
  4619. });
  4620. }
  4621. return e;
  4622. });
  4623. }
  4624. function shimMaxMessageSize(window, browserDetails) {
  4625. if (!window.RTCPeerConnection) {
  4626. return;
  4627. }
  4628. if (!('sctp' in window.RTCPeerConnection.prototype)) {
  4629. Object.defineProperty(window.RTCPeerConnection.prototype, 'sctp', {
  4630. get() {
  4631. return typeof this._sctp === 'undefined' ? null : this._sctp;
  4632. }
  4633. });
  4634. }
  4635. const sctpInDescription = function(description) {
  4636. if (!description || !description.sdp) {
  4637. return false;
  4638. }
  4639. const sections = sdp.splitSections(description.sdp);
  4640. sections.shift();
  4641. return sections.some(mediaSection => {
  4642. const mLine = sdp.parseMLine(mediaSection);
  4643. return mLine && mLine.kind === 'application'
  4644. && mLine.protocol.indexOf('SCTP') !== -1;
  4645. });
  4646. };
  4647. const getRemoteFirefoxVersion = function(description) {
  4648. // TODO: Is there a better solution for detecting Firefox?
  4649. const match = description.sdp.match(/mozilla...THIS_IS_SDPARTA-(\d+)/);
  4650. if (match === null || match.length < 2) {
  4651. return -1;
  4652. }
  4653. const version = parseInt(match[1], 10);
  4654. // Test for NaN (yes, this is ugly)
  4655. return version !== version ? -1 : version;
  4656. };
  4657. const getCanSendMaxMessageSize = function(remoteIsFirefox) {
  4658. // Every implementation we know can send at least 64 KiB.
  4659. // Note: Although Chrome is technically able to send up to 256 KiB, the
  4660. // data does not reach the other peer reliably.
  4661. // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=8419
  4662. let canSendMaxMessageSize = 65536;
  4663. if (browserDetails.browser === 'firefox') {
  4664. if (browserDetails.version < 57) {
  4665. if (remoteIsFirefox === -1) {
  4666. // FF < 57 will send in 16 KiB chunks using the deprecated PPID
  4667. // fragmentation.
  4668. canSendMaxMessageSize = 16384;
  4669. } else {
  4670. // However, other FF (and RAWRTC) can reassemble PPID-fragmented
  4671. // messages. Thus, supporting ~2 GiB when sending.
  4672. canSendMaxMessageSize = 2147483637;
  4673. }
  4674. } else if (browserDetails.version < 60) {
  4675. // Currently, all FF >= 57 will reset the remote maximum message size
  4676. // to the default value when a data channel is created at a later
  4677. // stage. :(
  4678. // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831
  4679. canSendMaxMessageSize =
  4680. browserDetails.version === 57 ? 65535 : 65536;
  4681. } else {
  4682. // FF >= 60 supports sending ~2 GiB
  4683. canSendMaxMessageSize = 2147483637;
  4684. }
  4685. }
  4686. return canSendMaxMessageSize;
  4687. };
  4688. const getMaxMessageSize = function(description, remoteIsFirefox) {
  4689. // Note: 65536 bytes is the default value from the SDP spec. Also,
  4690. // every implementation we know supports receiving 65536 bytes.
  4691. let maxMessageSize = 65536;
  4692. // FF 57 has a slightly incorrect default remote max message size, so
  4693. // we need to adjust it here to avoid a failure when sending.
  4694. // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1425697
  4695. if (browserDetails.browser === 'firefox'
  4696. && browserDetails.version === 57) {
  4697. maxMessageSize = 65535;
  4698. }
  4699. const match = sdp.matchPrefix(description.sdp,
  4700. 'a=max-message-size:');
  4701. if (match.length > 0) {
  4702. maxMessageSize = parseInt(match[0].substr(19), 10);
  4703. } else if (browserDetails.browser === 'firefox' &&
  4704. remoteIsFirefox !== -1) {
  4705. // If the maximum message size is not present in the remote SDP and
  4706. // both local and remote are Firefox, the remote peer can receive
  4707. // ~2 GiB.
  4708. maxMessageSize = 2147483637;
  4709. }
  4710. return maxMessageSize;
  4711. };
  4712. const origSetRemoteDescription =
  4713. window.RTCPeerConnection.prototype.setRemoteDescription;
  4714. window.RTCPeerConnection.prototype.setRemoteDescription =
  4715. function setRemoteDescription() {
  4716. this._sctp = null;
  4717. // Chrome decided to not expose .sctp in plan-b mode.
  4718. // As usual, adapter.js has to do an 'ugly worakaround'
  4719. // to cover up the mess.
  4720. if (browserDetails.browser === 'chrome' && browserDetails.version >= 76) {
  4721. const {sdpSemantics} = this.getConfiguration();
  4722. if (sdpSemantics === 'plan-b') {
  4723. Object.defineProperty(this, 'sctp', {
  4724. get() {
  4725. return typeof this._sctp === 'undefined' ? null : this._sctp;
  4726. },
  4727. enumerable: true,
  4728. configurable: true,
  4729. });
  4730. }
  4731. }
  4732. if (sctpInDescription(arguments[0])) {
  4733. // Check if the remote is FF.
  4734. const isFirefox = getRemoteFirefoxVersion(arguments[0]);
  4735. // Get the maximum message size the local peer is capable of sending
  4736. const canSendMMS = getCanSendMaxMessageSize(isFirefox);
  4737. // Get the maximum message size of the remote peer.
  4738. const remoteMMS = getMaxMessageSize(arguments[0], isFirefox);
  4739. // Determine final maximum message size
  4740. let maxMessageSize;
  4741. if (canSendMMS === 0 && remoteMMS === 0) {
  4742. maxMessageSize = Number.POSITIVE_INFINITY;
  4743. } else if (canSendMMS === 0 || remoteMMS === 0) {
  4744. maxMessageSize = Math.max(canSendMMS, remoteMMS);
  4745. } else {
  4746. maxMessageSize = Math.min(canSendMMS, remoteMMS);
  4747. }
  4748. // Create a dummy RTCSctpTransport object and the 'maxMessageSize'
  4749. // attribute.
  4750. const sctp = {};
  4751. Object.defineProperty(sctp, 'maxMessageSize', {
  4752. get() {
  4753. return maxMessageSize;
  4754. }
  4755. });
  4756. this._sctp = sctp;
  4757. }
  4758. return origSetRemoteDescription.apply(this, arguments);
  4759. };
  4760. }
  4761. function shimSendThrowTypeError(window) {
  4762. if (!(window.RTCPeerConnection &&
  4763. 'createDataChannel' in window.RTCPeerConnection.prototype)) {
  4764. return;
  4765. }
  4766. // Note: Although Firefox >= 57 has a native implementation, the maximum
  4767. // message size can be reset for all data channels at a later stage.
  4768. // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831
  4769. function wrapDcSend(dc, pc) {
  4770. const origDataChannelSend = dc.send;
  4771. dc.send = function send() {
  4772. const data = arguments[0];
  4773. const length = data.length || data.size || data.byteLength;
  4774. if (dc.readyState === 'open' &&
  4775. pc.sctp && length > pc.sctp.maxMessageSize) {
  4776. throw new TypeError('Message too large (can send a maximum of ' +
  4777. pc.sctp.maxMessageSize + ' bytes)');
  4778. }
  4779. return origDataChannelSend.apply(dc, arguments);
  4780. };
  4781. }
  4782. const origCreateDataChannel =
  4783. window.RTCPeerConnection.prototype.createDataChannel;
  4784. window.RTCPeerConnection.prototype.createDataChannel =
  4785. function createDataChannel() {
  4786. const dataChannel = origCreateDataChannel.apply(this, arguments);
  4787. wrapDcSend(dataChannel, this);
  4788. return dataChannel;
  4789. };
  4790. wrapPeerConnectionEvent(window, 'datachannel', e => {
  4791. wrapDcSend(e.channel, e.target);
  4792. return e;
  4793. });
  4794. }
  4795. /* shims RTCConnectionState by pretending it is the same as iceConnectionState.
  4796. * See https://bugs.chromium.org/p/webrtc/issues/detail?id=6145#c12
  4797. * for why this is a valid hack in Chrome. In Firefox it is slightly incorrect
  4798. * since DTLS failures would be hidden. See
  4799. * https://bugzilla.mozilla.org/show_bug.cgi?id=1265827
  4800. * for the Firefox tracking bug.
  4801. */
  4802. function shimConnectionState(window) {
  4803. if (!window.RTCPeerConnection ||
  4804. 'connectionState' in window.RTCPeerConnection.prototype) {
  4805. return;
  4806. }
  4807. const proto = window.RTCPeerConnection.prototype;
  4808. Object.defineProperty(proto, 'connectionState', {
  4809. get() {
  4810. return {
  4811. completed: 'connected',
  4812. checking: 'connecting'
  4813. }[this.iceConnectionState] || this.iceConnectionState;
  4814. },
  4815. enumerable: true,
  4816. configurable: true
  4817. });
  4818. Object.defineProperty(proto, 'onconnectionstatechange', {
  4819. get() {
  4820. return this._onconnectionstatechange || null;
  4821. },
  4822. set(cb) {
  4823. if (this._onconnectionstatechange) {
  4824. this.removeEventListener('connectionstatechange',
  4825. this._onconnectionstatechange);
  4826. delete this._onconnectionstatechange;
  4827. }
  4828. if (cb) {
  4829. this.addEventListener('connectionstatechange',
  4830. this._onconnectionstatechange = cb);
  4831. }
  4832. },
  4833. enumerable: true,
  4834. configurable: true
  4835. });
  4836. ['setLocalDescription', 'setRemoteDescription'].forEach((method) => {
  4837. const origMethod = proto[method];
  4838. proto[method] = function() {
  4839. if (!this._connectionstatechangepoly) {
  4840. this._connectionstatechangepoly = e => {
  4841. const pc = e.target;
  4842. if (pc._lastConnectionState !== pc.connectionState) {
  4843. pc._lastConnectionState = pc.connectionState;
  4844. const newEvent = new Event('connectionstatechange', e);
  4845. pc.dispatchEvent(newEvent);
  4846. }
  4847. return e;
  4848. };
  4849. this.addEventListener('iceconnectionstatechange',
  4850. this._connectionstatechangepoly);
  4851. }
  4852. return origMethod.apply(this, arguments);
  4853. };
  4854. });
  4855. }
  4856. function removeExtmapAllowMixed(window, browserDetails) {
  4857. /* remove a=extmap-allow-mixed for webrtc.org < M71 */
  4858. if (!window.RTCPeerConnection) {
  4859. return;
  4860. }
  4861. if (browserDetails.browser === 'chrome' && browserDetails.version >= 71) {
  4862. return;
  4863. }
  4864. if (browserDetails.browser === 'safari' && browserDetails.version >= 605) {
  4865. return;
  4866. }
  4867. const nativeSRD = window.RTCPeerConnection.prototype.setRemoteDescription;
  4868. window.RTCPeerConnection.prototype.setRemoteDescription =
  4869. function setRemoteDescription(desc) {
  4870. if (desc && desc.sdp && desc.sdp.indexOf('\na=extmap-allow-mixed') !== -1) {
  4871. const sdp = desc.sdp.split('\n').filter((line) => {
  4872. return line.trim() !== 'a=extmap-allow-mixed';
  4873. }).join('\n');
  4874. // Safari enforces read-only-ness of RTCSessionDescription fields.
  4875. if (window.RTCSessionDescription &&
  4876. desc instanceof window.RTCSessionDescription) {
  4877. arguments[0] = new window.RTCSessionDescription({
  4878. type: desc.type,
  4879. sdp,
  4880. });
  4881. } else {
  4882. desc.sdp = sdp;
  4883. }
  4884. }
  4885. return nativeSRD.apply(this, arguments);
  4886. };
  4887. }
  4888. function shimAddIceCandidateNullOrEmpty(window, browserDetails) {
  4889. // Support for addIceCandidate(null or undefined)
  4890. // as well as addIceCandidate({candidate: "", ...})
  4891. // https://bugs.chromium.org/p/chromium/issues/detail?id=978582
  4892. // Note: must be called before other polyfills which change the signature.
  4893. if (!(window.RTCPeerConnection && window.RTCPeerConnection.prototype)) {
  4894. return;
  4895. }
  4896. const nativeAddIceCandidate =
  4897. window.RTCPeerConnection.prototype.addIceCandidate;
  4898. if (!nativeAddIceCandidate || nativeAddIceCandidate.length === 0) {
  4899. return;
  4900. }
  4901. window.RTCPeerConnection.prototype.addIceCandidate =
  4902. function addIceCandidate() {
  4903. if (!arguments[0]) {
  4904. if (arguments[1]) {
  4905. arguments[1].apply(null);
  4906. }
  4907. return Promise.resolve();
  4908. }
  4909. // Firefox 68+ emits and processes {candidate: "", ...}, ignore
  4910. // in older versions.
  4911. // Native support for ignoring exists for Chrome M77+.
  4912. // Safari ignores as well, exact version unknown but works in the same
  4913. // version that also ignores addIceCandidate(null).
  4914. if (((browserDetails.browser === 'chrome' && browserDetails.version < 78)
  4915. || (browserDetails.browser === 'firefox'
  4916. && browserDetails.version < 68)
  4917. || (browserDetails.browser === 'safari'))
  4918. && arguments[0] && arguments[0].candidate === '') {
  4919. return Promise.resolve();
  4920. }
  4921. return nativeAddIceCandidate.apply(this, arguments);
  4922. };
  4923. }
  4924. var commonShim = /*#__PURE__*/Object.freeze({
  4925. __proto__: null,
  4926. shimRTCIceCandidate: shimRTCIceCandidate,
  4927. shimMaxMessageSize: shimMaxMessageSize,
  4928. shimSendThrowTypeError: shimSendThrowTypeError,
  4929. shimConnectionState: shimConnectionState,
  4930. removeExtmapAllowMixed: removeExtmapAllowMixed,
  4931. shimAddIceCandidateNullOrEmpty: shimAddIceCandidateNullOrEmpty
  4932. });
  4933. /*
  4934. * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
  4935. *
  4936. * Use of this source code is governed by a BSD-style license
  4937. * that can be found in the LICENSE file in the root of the source
  4938. * tree.
  4939. */
  4940. // Shimming starts here.
  4941. function adapterFactory({window} = {}, options = {
  4942. shimChrome: true,
  4943. shimFirefox: true,
  4944. shimEdge: true,
  4945. shimSafari: true,
  4946. }) {
  4947. // Utils.
  4948. const logging = log$1;
  4949. const browserDetails = detectBrowser(window);
  4950. const adapter = {
  4951. browserDetails,
  4952. commonShim,
  4953. extractVersion: extractVersion,
  4954. disableLog: disableLog,
  4955. disableWarnings: disableWarnings
  4956. };
  4957. // Shim browser if found.
  4958. switch (browserDetails.browser) {
  4959. case 'chrome':
  4960. if (!chromeShim || !shimPeerConnection$2 ||
  4961. !options.shimChrome) {
  4962. logging('Chrome shim is not included in this adapter release.');
  4963. return adapter;
  4964. }
  4965. if (browserDetails.version === null) {
  4966. logging('Chrome shim can not determine version, not shimming.');
  4967. return adapter;
  4968. }
  4969. logging('adapter.js shimming chrome.');
  4970. // Export to the adapter global object visible in the browser.
  4971. adapter.browserShim = chromeShim;
  4972. // Must be called before shimPeerConnection.
  4973. shimAddIceCandidateNullOrEmpty(window, browserDetails);
  4974. shimGetUserMedia$3(window, browserDetails);
  4975. shimMediaStream(window);
  4976. shimPeerConnection$2(window, browserDetails);
  4977. shimOnTrack$1(window);
  4978. shimAddTrackRemoveTrack(window, browserDetails);
  4979. shimGetSendersWithDtmf(window);
  4980. shimGetStats(window);
  4981. shimSenderReceiverGetStats(window);
  4982. fixNegotiationNeeded(window, browserDetails);
  4983. shimRTCIceCandidate(window);
  4984. shimConnectionState(window);
  4985. shimMaxMessageSize(window, browserDetails);
  4986. shimSendThrowTypeError(window);
  4987. removeExtmapAllowMixed(window, browserDetails);
  4988. break;
  4989. case 'firefox':
  4990. if (!firefoxShim || !shimPeerConnection ||
  4991. !options.shimFirefox) {
  4992. logging('Firefox shim is not included in this adapter release.');
  4993. return adapter;
  4994. }
  4995. logging('adapter.js shimming firefox.');
  4996. // Export to the adapter global object visible in the browser.
  4997. adapter.browserShim = firefoxShim;
  4998. // Must be called before shimPeerConnection.
  4999. shimAddIceCandidateNullOrEmpty(window, browserDetails);
  5000. shimGetUserMedia$1(window, browserDetails);
  5001. shimPeerConnection(window, browserDetails);
  5002. shimOnTrack(window);
  5003. shimRemoveStream(window);
  5004. shimSenderGetStats(window);
  5005. shimReceiverGetStats(window);
  5006. shimRTCDataChannel(window);
  5007. shimAddTransceiver(window);
  5008. shimGetParameters(window);
  5009. shimCreateOffer(window);
  5010. shimCreateAnswer(window);
  5011. shimRTCIceCandidate(window);
  5012. shimConnectionState(window);
  5013. shimMaxMessageSize(window, browserDetails);
  5014. shimSendThrowTypeError(window);
  5015. break;
  5016. case 'edge':
  5017. if (!edgeShim || !shimPeerConnection$1 || !options.shimEdge) {
  5018. logging('MS edge shim is not included in this adapter release.');
  5019. return adapter;
  5020. }
  5021. logging('adapter.js shimming edge.');
  5022. // Export to the adapter global object visible in the browser.
  5023. adapter.browserShim = edgeShim;
  5024. shimGetUserMedia$2(window);
  5025. shimGetDisplayMedia$1(window);
  5026. shimPeerConnection$1(window, browserDetails);
  5027. shimReplaceTrack(window);
  5028. // the edge shim implements the full RTCIceCandidate object.
  5029. shimMaxMessageSize(window, browserDetails);
  5030. shimSendThrowTypeError(window);
  5031. break;
  5032. case 'safari':
  5033. if (!safariShim || !options.shimSafari) {
  5034. logging('Safari shim is not included in this adapter release.');
  5035. return adapter;
  5036. }
  5037. logging('adapter.js shimming safari.');
  5038. // Export to the adapter global object visible in the browser.
  5039. adapter.browserShim = safariShim;
  5040. // Must be called before shimCallbackAPI.
  5041. shimAddIceCandidateNullOrEmpty(window, browserDetails);
  5042. shimRTCIceServerUrls(window);
  5043. shimCreateOfferLegacy(window);
  5044. shimCallbacksAPI(window);
  5045. shimLocalStreamsAPI(window);
  5046. shimRemoteStreamsAPI(window);
  5047. shimTrackEventTransceiver(window);
  5048. shimGetUserMedia(window);
  5049. shimAudioContext(window);
  5050. shimRTCIceCandidate(window);
  5051. shimMaxMessageSize(window, browserDetails);
  5052. shimSendThrowTypeError(window);
  5053. removeExtmapAllowMixed(window, browserDetails);
  5054. break;
  5055. default:
  5056. logging('Unsupported browser!');
  5057. break;
  5058. }
  5059. return adapter;
  5060. }
  5061. /*
  5062. * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
  5063. *
  5064. * Use of this source code is governed by a BSD-style license
  5065. * that can be found in the LICENSE file in the root of the source
  5066. * tree.
  5067. */
  5068. adapterFactory({window: typeof window === 'undefined' ? undefined : window});
  5069. /**
  5070. * @class AudioTrackConstraints
  5071. * @classDesc Constraints for creating an audio MediaStreamTrack.
  5072. * @memberof Owt.Base
  5073. * @constructor
  5074. * @param {Owt.Base.AudioSourceInfo} source Source info of this audio track.
  5075. */
  5076. class AudioTrackConstraints {
  5077. // eslint-disable-next-line require-jsdoc
  5078. constructor(source) {
  5079. if (!Object.values(AudioSourceInfo).some(v => v === source)) {
  5080. throw new TypeError('Invalid source.');
  5081. }
  5082. /**
  5083. * @member {string} source
  5084. * @memberof Owt.Base.AudioTrackConstraints
  5085. * @desc Values could be "mic", "screen-cast", "file" or "mixed".
  5086. * @instance
  5087. */
  5088. this.source = source;
  5089. /**
  5090. * @member {string} deviceId
  5091. * @memberof Owt.Base.AudioTrackConstraints
  5092. * @desc Do not provide deviceId if source is not "mic".
  5093. * @instance
  5094. * @see https://w3c.github.io/mediacapture-main/#def-constraint-deviceId
  5095. */
  5096. this.deviceId = undefined;
  5097. }
  5098. }
  5099. /**
  5100. * @class VideoTrackConstraints
  5101. * @classDesc Constraints for creating a video MediaStreamTrack.
  5102. * @memberof Owt.Base
  5103. * @constructor
  5104. * @param {Owt.Base.VideoSourceInfo} source Source info of this video track.
  5105. */
  5106. class VideoTrackConstraints {
  5107. // eslint-disable-next-line require-jsdoc
  5108. constructor(source) {
  5109. if (!Object.values(VideoSourceInfo).some(v => v === source)) {
  5110. throw new TypeError('Invalid source.');
  5111. }
  5112. /**
  5113. * @member {string} source
  5114. * @memberof Owt.Base.VideoTrackConstraints
  5115. * @desc Values could be "camera", "screen-cast", "file" or "mixed".
  5116. * @instance
  5117. */
  5118. this.source = source;
  5119. /**
  5120. * @member {string} deviceId
  5121. * @memberof Owt.Base.VideoTrackConstraints
  5122. * @desc Do not provide deviceId if source is not "camera".
  5123. * @instance
  5124. * @see https://w3c.github.io/mediacapture-main/#def-constraint-deviceId
  5125. */
  5126. this.deviceId = undefined;
  5127. /**
  5128. * @member {Owt.Base.Resolution} resolution
  5129. * @memberof Owt.Base.VideoTrackConstraints
  5130. * @instance
  5131. */
  5132. this.resolution = undefined;
  5133. /**
  5134. * @member {number} frameRate
  5135. * @memberof Owt.Base.VideoTrackConstraints
  5136. * @instance
  5137. */
  5138. this.frameRate = undefined;
  5139. }
  5140. }
  5141. /**
  5142. * @class StreamConstraints
  5143. * @classDesc Constraints for creating a MediaStream from screen mic and camera.
  5144. * @memberof Owt.Base
  5145. * @constructor
  5146. * @param {?Owt.Base.AudioTrackConstraints} audioConstraints
  5147. * @param {?Owt.Base.VideoTrackConstraints} videoConstraints
  5148. */
  5149. class StreamConstraints {
  5150. // eslint-disable-next-line require-jsdoc
  5151. constructor(audioConstraints = false, videoConstraints = false) {
  5152. /**
  5153. * @member {Owt.Base.MediaStreamTrackDeviceConstraintsForAudio} audio
  5154. * @memberof Owt.Base.MediaStreamDeviceConstraints
  5155. * @instance
  5156. */
  5157. this.audio = audioConstraints;
  5158. /**
  5159. * @member {Owt.Base.MediaStreamTrackDeviceConstraintsForVideo} Video
  5160. * @memberof Owt.Base.MediaStreamDeviceConstraints
  5161. * @instance
  5162. */
  5163. this.video = videoConstraints;
  5164. }
  5165. }
  5166. // eslint-disable-next-line require-jsdoc
  5167. function isVideoConstrainsForScreenCast(constraints) {
  5168. return typeof constraints.video === 'object' && constraints.video.source === VideoSourceInfo.SCREENCAST;
  5169. }
  5170. /**
  5171. * @class MediaStreamFactory
  5172. * @classDesc A factory to create MediaStream. You can also create MediaStream by yourself.
  5173. * @memberof Owt.Base
  5174. */
  5175. class MediaStreamFactory {
  5176. /**
  5177. * @function createMediaStream
  5178. * @static
  5179. * @desc Create a MediaStream with given constraints. If you want to create a MediaStream for screen cast, please make sure both audio and video's source are "screen-cast".
  5180. * @memberof Owt.Base.MediaStreamFactory
  5181. * @return {Promise<MediaStream, Error>} Return a promise that is resolved when stream is successfully created, or rejected if one of the following error happened:
  5182. * - One or more parameters cannot be satisfied.
  5183. * - Specified device is busy.
  5184. * - Cannot obtain necessary permission or operation is canceled by user.
  5185. * - Video source is screen cast, while audio source is not.
  5186. * - Audio source is screen cast, while video source is disabled.
  5187. * @param {Owt.Base.StreamConstraints} constraints
  5188. */
  5189. static createMediaStream(constraints) {
  5190. if (typeof constraints !== 'object' || !constraints.audio && !constraints.video) {
  5191. return Promise.reject(new TypeError('Invalid constrains'));
  5192. }
  5193. if (!isVideoConstrainsForScreenCast(constraints) && typeof constraints.audio === 'object' && constraints.audio.source === AudioSourceInfo.SCREENCAST) {
  5194. return Promise.reject(new TypeError('Cannot share screen without video.'));
  5195. }
  5196. if (isVideoConstrainsForScreenCast(constraints) && !isChrome() && !isFirefox()) {
  5197. return Promise.reject(new TypeError('Screen sharing only supports Chrome and Firefox.'));
  5198. }
  5199. if (isVideoConstrainsForScreenCast(constraints) && typeof constraints.audio === 'object' && constraints.audio.source !== AudioSourceInfo.SCREENCAST) {
  5200. return Promise.reject(new TypeError('Cannot capture video from screen cast while capture audio from' + ' other source.'));
  5201. }
  5202. // Check and convert constraints.
  5203. if (!constraints.audio && !constraints.video) {
  5204. return Promise.reject(new TypeError('At least one of audio and video must be requested.'));
  5205. }
  5206. const mediaConstraints = Object.create({});
  5207. if (typeof constraints.audio === 'object' && constraints.audio.source === AudioSourceInfo.MIC) {
  5208. mediaConstraints.audio = Object.create({});
  5209. if (isEdge()) {
  5210. mediaConstraints.audio.deviceId = constraints.audio.deviceId;
  5211. } else {
  5212. mediaConstraints.audio.deviceId = {
  5213. exact: constraints.audio.deviceId
  5214. };
  5215. }
  5216. } else {
  5217. if (constraints.audio.source === AudioSourceInfo.SCREENCAST) {
  5218. mediaConstraints.audio = true;
  5219. } else {
  5220. mediaConstraints.audio = constraints.audio;
  5221. }
  5222. }
  5223. if (typeof constraints.video === 'object') {
  5224. mediaConstraints.video = Object.create({});
  5225. if (typeof constraints.video.frameRate === 'number') {
  5226. mediaConstraints.video.frameRate = constraints.video.frameRate;
  5227. }
  5228. if (constraints.video.resolution && constraints.video.resolution.width && constraints.video.resolution.height) {
  5229. if (constraints.video.source === VideoSourceInfo.SCREENCAST) {
  5230. mediaConstraints.video.width = constraints.video.resolution.width;
  5231. mediaConstraints.video.height = constraints.video.resolution.height;
  5232. } else {
  5233. mediaConstraints.video.width = Object.create({});
  5234. mediaConstraints.video.width.exact = constraints.video.resolution.width;
  5235. mediaConstraints.video.height = Object.create({});
  5236. mediaConstraints.video.height.exact = constraints.video.resolution.height;
  5237. }
  5238. }
  5239. if (typeof constraints.video.deviceId === 'string') {
  5240. mediaConstraints.video.deviceId = {
  5241. exact: constraints.video.deviceId
  5242. };
  5243. }
  5244. if (isFirefox() && constraints.video.source === VideoSourceInfo.SCREENCAST) {
  5245. mediaConstraints.video.mediaSource = 'screen';
  5246. }
  5247. } else {
  5248. mediaConstraints.video = constraints.video;
  5249. }
  5250. if (isVideoConstrainsForScreenCast(constraints)) {
  5251. return navigator.mediaDevices.getDisplayMedia(mediaConstraints);
  5252. } else {
  5253. return navigator.mediaDevices.getUserMedia(mediaConstraints);
  5254. }
  5255. }
  5256. }
  5257. // Copyright (C) <2018> Intel Corporation
  5258. var media = /*#__PURE__*/Object.freeze({
  5259. __proto__: null,
  5260. AudioTrackConstraints: AudioTrackConstraints,
  5261. VideoTrackConstraints: VideoTrackConstraints,
  5262. StreamConstraints: StreamConstraints,
  5263. MediaStreamFactory: MediaStreamFactory,
  5264. AudioSourceInfo: AudioSourceInfo,
  5265. VideoSourceInfo: VideoSourceInfo,
  5266. TrackKind: TrackKind,
  5267. Resolution: Resolution
  5268. });
  5269. let logger;
  5270. let errorLogger;
  5271. function setLogger() {
  5272. /*eslint-disable */
  5273. logger = console.log;
  5274. errorLogger = console.error;
  5275. /*eslint-enable */
  5276. }
  5277. function log(message, ...optionalParams) {
  5278. if (logger) {
  5279. logger(message, ...optionalParams);
  5280. }
  5281. }
  5282. function error(message, ...optionalParams) {
  5283. if (errorLogger) {
  5284. errorLogger(message, ...optionalParams);
  5285. }
  5286. }
  5287. class Event$1 {
  5288. constructor(type) {
  5289. this.listener = {};
  5290. this.type = type | '';
  5291. }
  5292. on(event, fn) {
  5293. if (!this.listener[event]) {
  5294. this.listener[event] = [];
  5295. }
  5296. this.listener[event].push(fn);
  5297. return true;
  5298. }
  5299. off(event, fn) {
  5300. if (this.listener[event]) {
  5301. var index = this.listener[event].indexOf(fn);
  5302. if (index > -1) {
  5303. this.listener[event].splice(index, 1);
  5304. }
  5305. return true;
  5306. }
  5307. return false;
  5308. }
  5309. offAll() {
  5310. this.listener = {};
  5311. }
  5312. dispatch(event, data) {
  5313. if (this.listener[event]) {
  5314. this.listener[event].map(each => {
  5315. each.apply(null, [data]);
  5316. });
  5317. return true;
  5318. }
  5319. return false;
  5320. }
  5321. }
  5322. var bind = function bind(fn, thisArg) {
  5323. return function wrap() {
  5324. var args = new Array(arguments.length);
  5325. for (var i = 0; i < args.length; i++) {
  5326. args[i] = arguments[i];
  5327. }
  5328. return fn.apply(thisArg, args);
  5329. };
  5330. };
  5331. // utils is a library of generic helper functions non-specific to axios
  5332. var toString = Object.prototype.toString;
  5333. // eslint-disable-next-line func-names
  5334. var kindOf = (function(cache) {
  5335. // eslint-disable-next-line func-names
  5336. return function(thing) {
  5337. var str = toString.call(thing);
  5338. return cache[str] || (cache[str] = str.slice(8, -1).toLowerCase());
  5339. };
  5340. })(Object.create(null));
  5341. function kindOfTest(type) {
  5342. type = type.toLowerCase();
  5343. return function isKindOf(thing) {
  5344. return kindOf(thing) === type;
  5345. };
  5346. }
  5347. /**
  5348. * Determine if a value is an Array
  5349. *
  5350. * @param {Object} val The value to test
  5351. * @returns {boolean} True if value is an Array, otherwise false
  5352. */
  5353. function isArray(val) {
  5354. return Array.isArray(val);
  5355. }
  5356. /**
  5357. * Determine if a value is undefined
  5358. *
  5359. * @param {Object} val The value to test
  5360. * @returns {boolean} True if the value is undefined, otherwise false
  5361. */
  5362. function isUndefined(val) {
  5363. return typeof val === 'undefined';
  5364. }
  5365. /**
  5366. * Determine if a value is a Buffer
  5367. *
  5368. * @param {Object} val The value to test
  5369. * @returns {boolean} True if value is a Buffer, otherwise false
  5370. */
  5371. function isBuffer(val) {
  5372. return val !== null && !isUndefined(val) && val.constructor !== null && !isUndefined(val.constructor)
  5373. && typeof val.constructor.isBuffer === 'function' && val.constructor.isBuffer(val);
  5374. }
  5375. /**
  5376. * Determine if a value is an ArrayBuffer
  5377. *
  5378. * @function
  5379. * @param {Object} val The value to test
  5380. * @returns {boolean} True if value is an ArrayBuffer, otherwise false
  5381. */
  5382. var isArrayBuffer = kindOfTest('ArrayBuffer');
  5383. /**
  5384. * Determine if a value is a view on an ArrayBuffer
  5385. *
  5386. * @param {Object} val The value to test
  5387. * @returns {boolean} True if value is a view on an ArrayBuffer, otherwise false
  5388. */
  5389. function isArrayBufferView(val) {
  5390. var result;
  5391. if ((typeof ArrayBuffer !== 'undefined') && (ArrayBuffer.isView)) {
  5392. result = ArrayBuffer.isView(val);
  5393. } else {
  5394. result = (val) && (val.buffer) && (isArrayBuffer(val.buffer));
  5395. }
  5396. return result;
  5397. }
  5398. /**
  5399. * Determine if a value is a String
  5400. *
  5401. * @param {Object} val The value to test
  5402. * @returns {boolean} True if value is a String, otherwise false
  5403. */
  5404. function isString(val) {
  5405. return typeof val === 'string';
  5406. }
  5407. /**
  5408. * Determine if a value is a Number
  5409. *
  5410. * @param {Object} val The value to test
  5411. * @returns {boolean} True if value is a Number, otherwise false
  5412. */
  5413. function isNumber(val) {
  5414. return typeof val === 'number';
  5415. }
  5416. /**
  5417. * Determine if a value is an Object
  5418. *
  5419. * @param {Object} val The value to test
  5420. * @returns {boolean} True if value is an Object, otherwise false
  5421. */
  5422. function isObject(val) {
  5423. return val !== null && typeof val === 'object';
  5424. }
  5425. /**
  5426. * Determine if a value is a plain Object
  5427. *
  5428. * @param {Object} val The value to test
  5429. * @return {boolean} True if value is a plain Object, otherwise false
  5430. */
  5431. function isPlainObject(val) {
  5432. if (kindOf(val) !== 'object') {
  5433. return false;
  5434. }
  5435. var prototype = Object.getPrototypeOf(val);
  5436. return prototype === null || prototype === Object.prototype;
  5437. }
  5438. /**
  5439. * Determine if a value is a Date
  5440. *
  5441. * @function
  5442. * @param {Object} val The value to test
  5443. * @returns {boolean} True if value is a Date, otherwise false
  5444. */
  5445. var isDate = kindOfTest('Date');
  5446. /**
  5447. * Determine if a value is a File
  5448. *
  5449. * @function
  5450. * @param {Object} val The value to test
  5451. * @returns {boolean} True if value is a File, otherwise false
  5452. */
  5453. var isFile = kindOfTest('File');
  5454. /**
  5455. * Determine if a value is a Blob
  5456. *
  5457. * @function
  5458. * @param {Object} val The value to test
  5459. * @returns {boolean} True if value is a Blob, otherwise false
  5460. */
  5461. var isBlob = kindOfTest('Blob');
  5462. /**
  5463. * Determine if a value is a FileList
  5464. *
  5465. * @function
  5466. * @param {Object} val The value to test
  5467. * @returns {boolean} True if value is a File, otherwise false
  5468. */
  5469. var isFileList = kindOfTest('FileList');
  5470. /**
  5471. * Determine if a value is a Function
  5472. *
  5473. * @param {Object} val The value to test
  5474. * @returns {boolean} True if value is a Function, otherwise false
  5475. */
  5476. function isFunction(val) {
  5477. return toString.call(val) === '[object Function]';
  5478. }
  5479. /**
  5480. * Determine if a value is a Stream
  5481. *
  5482. * @param {Object} val The value to test
  5483. * @returns {boolean} True if value is a Stream, otherwise false
  5484. */
  5485. function isStream(val) {
  5486. return isObject(val) && isFunction(val.pipe);
  5487. }
  5488. /**
  5489. * Determine if a value is a FormData
  5490. *
  5491. * @param {Object} thing The value to test
  5492. * @returns {boolean} True if value is an FormData, otherwise false
  5493. */
  5494. function isFormData(thing) {
  5495. var pattern = '[object FormData]';
  5496. return thing && (
  5497. (typeof FormData === 'function' && thing instanceof FormData) ||
  5498. toString.call(thing) === pattern ||
  5499. (isFunction(thing.toString) && thing.toString() === pattern)
  5500. );
  5501. }
  5502. /**
  5503. * Determine if a value is a URLSearchParams object
  5504. * @function
  5505. * @param {Object} val The value to test
  5506. * @returns {boolean} True if value is a URLSearchParams object, otherwise false
  5507. */
  5508. var isURLSearchParams = kindOfTest('URLSearchParams');
  5509. /**
  5510. * Trim excess whitespace off the beginning and end of a string
  5511. *
  5512. * @param {String} str The String to trim
  5513. * @returns {String} The String freed of excess whitespace
  5514. */
  5515. function trim(str) {
  5516. return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g, '');
  5517. }
  5518. /**
  5519. * Determine if we're running in a standard browser environment
  5520. *
  5521. * This allows axios to run in a web worker, and react-native.
  5522. * Both environments support XMLHttpRequest, but not fully standard globals.
  5523. *
  5524. * web workers:
  5525. * typeof window -> undefined
  5526. * typeof document -> undefined
  5527. *
  5528. * react-native:
  5529. * navigator.product -> 'ReactNative'
  5530. * nativescript
  5531. * navigator.product -> 'NativeScript' or 'NS'
  5532. */
  5533. function isStandardBrowserEnv() {
  5534. if (typeof navigator !== 'undefined' && (navigator.product === 'ReactNative' ||
  5535. navigator.product === 'NativeScript' ||
  5536. navigator.product === 'NS')) {
  5537. return false;
  5538. }
  5539. return (
  5540. typeof window !== 'undefined' &&
  5541. typeof document !== 'undefined'
  5542. );
  5543. }
  5544. /**
  5545. * Iterate over an Array or an Object invoking a function for each item.
  5546. *
  5547. * If `obj` is an Array callback will be called passing
  5548. * the value, index, and complete array for each item.
  5549. *
  5550. * If 'obj' is an Object callback will be called passing
  5551. * the value, key, and complete object for each property.
  5552. *
  5553. * @param {Object|Array} obj The object to iterate
  5554. * @param {Function} fn The callback to invoke for each item
  5555. */
  5556. function forEach(obj, fn) {
  5557. // Don't bother if no value provided
  5558. if (obj === null || typeof obj === 'undefined') {
  5559. return;
  5560. }
  5561. // Force an array if not already something iterable
  5562. if (typeof obj !== 'object') {
  5563. /*eslint no-param-reassign:0*/
  5564. obj = [obj];
  5565. }
  5566. if (isArray(obj)) {
  5567. // Iterate over array values
  5568. for (var i = 0, l = obj.length; i < l; i++) {
  5569. fn.call(null, obj[i], i, obj);
  5570. }
  5571. } else {
  5572. // Iterate over object keys
  5573. for (var key in obj) {
  5574. if (Object.prototype.hasOwnProperty.call(obj, key)) {
  5575. fn.call(null, obj[key], key, obj);
  5576. }
  5577. }
  5578. }
  5579. }
  5580. /**
  5581. * Accepts varargs expecting each argument to be an object, then
  5582. * immutably merges the properties of each object and returns result.
  5583. *
  5584. * When multiple objects contain the same key the later object in
  5585. * the arguments list will take precedence.
  5586. *
  5587. * Example:
  5588. *
  5589. * ```js
  5590. * var result = merge({foo: 123}, {foo: 456});
  5591. * console.log(result.foo); // outputs 456
  5592. * ```
  5593. *
  5594. * @param {Object} obj1 Object to merge
  5595. * @returns {Object} Result of all merge properties
  5596. */
  5597. function merge(/* obj1, obj2, obj3, ... */) {
  5598. var result = {};
  5599. function assignValue(val, key) {
  5600. if (isPlainObject(result[key]) && isPlainObject(val)) {
  5601. result[key] = merge(result[key], val);
  5602. } else if (isPlainObject(val)) {
  5603. result[key] = merge({}, val);
  5604. } else if (isArray(val)) {
  5605. result[key] = val.slice();
  5606. } else {
  5607. result[key] = val;
  5608. }
  5609. }
  5610. for (var i = 0, l = arguments.length; i < l; i++) {
  5611. forEach(arguments[i], assignValue);
  5612. }
  5613. return result;
  5614. }
  5615. /**
  5616. * Extends object a by mutably adding to it the properties of object b.
  5617. *
  5618. * @param {Object} a The object to be extended
  5619. * @param {Object} b The object to copy properties from
  5620. * @param {Object} thisArg The object to bind function to
  5621. * @return {Object} The resulting value of object a
  5622. */
  5623. function extend(a, b, thisArg) {
  5624. forEach(b, function assignValue(val, key) {
  5625. if (thisArg && typeof val === 'function') {
  5626. a[key] = bind(val, thisArg);
  5627. } else {
  5628. a[key] = val;
  5629. }
  5630. });
  5631. return a;
  5632. }
  5633. /**
  5634. * Remove byte order marker. This catches EF BB BF (the UTF-8 BOM)
  5635. *
  5636. * @param {string} content with BOM
  5637. * @return {string} content value without BOM
  5638. */
  5639. function stripBOM(content) {
  5640. if (content.charCodeAt(0) === 0xFEFF) {
  5641. content = content.slice(1);
  5642. }
  5643. return content;
  5644. }
  5645. /**
  5646. * Inherit the prototype methods from one constructor into another
  5647. * @param {function} constructor
  5648. * @param {function} superConstructor
  5649. * @param {object} [props]
  5650. * @param {object} [descriptors]
  5651. */
  5652. function inherits(constructor, superConstructor, props, descriptors) {
  5653. constructor.prototype = Object.create(superConstructor.prototype, descriptors);
  5654. constructor.prototype.constructor = constructor;
  5655. props && Object.assign(constructor.prototype, props);
  5656. }
  5657. /**
  5658. * Resolve object with deep prototype chain to a flat object
  5659. * @param {Object} sourceObj source object
  5660. * @param {Object} [destObj]
  5661. * @param {Function} [filter]
  5662. * @returns {Object}
  5663. */
  5664. function toFlatObject(sourceObj, destObj, filter) {
  5665. var props;
  5666. var i;
  5667. var prop;
  5668. var merged = {};
  5669. destObj = destObj || {};
  5670. do {
  5671. props = Object.getOwnPropertyNames(sourceObj);
  5672. i = props.length;
  5673. while (i-- > 0) {
  5674. prop = props[i];
  5675. if (!merged[prop]) {
  5676. destObj[prop] = sourceObj[prop];
  5677. merged[prop] = true;
  5678. }
  5679. }
  5680. sourceObj = Object.getPrototypeOf(sourceObj);
  5681. } while (sourceObj && (!filter || filter(sourceObj, destObj)) && sourceObj !== Object.prototype);
  5682. return destObj;
  5683. }
  5684. /*
  5685. * determines whether a string ends with the characters of a specified string
  5686. * @param {String} str
  5687. * @param {String} searchString
  5688. * @param {Number} [position= 0]
  5689. * @returns {boolean}
  5690. */
  5691. function endsWith(str, searchString, position) {
  5692. str = String(str);
  5693. if (position === undefined || position > str.length) {
  5694. position = str.length;
  5695. }
  5696. position -= searchString.length;
  5697. var lastIndex = str.indexOf(searchString, position);
  5698. return lastIndex !== -1 && lastIndex === position;
  5699. }
  5700. /**
  5701. * Returns new array from array like object
  5702. * @param {*} [thing]
  5703. * @returns {Array}
  5704. */
  5705. function toArray(thing) {
  5706. if (!thing) return null;
  5707. var i = thing.length;
  5708. if (isUndefined(i)) return null;
  5709. var arr = new Array(i);
  5710. while (i-- > 0) {
  5711. arr[i] = thing[i];
  5712. }
  5713. return arr;
  5714. }
  5715. // eslint-disable-next-line func-names
  5716. var isTypedArray = (function(TypedArray) {
  5717. // eslint-disable-next-line func-names
  5718. return function(thing) {
  5719. return TypedArray && thing instanceof TypedArray;
  5720. };
  5721. })(typeof Uint8Array !== 'undefined' && Object.getPrototypeOf(Uint8Array));
  5722. var utils = {
  5723. isArray: isArray,
  5724. isArrayBuffer: isArrayBuffer,
  5725. isBuffer: isBuffer,
  5726. isFormData: isFormData,
  5727. isArrayBufferView: isArrayBufferView,
  5728. isString: isString,
  5729. isNumber: isNumber,
  5730. isObject: isObject,
  5731. isPlainObject: isPlainObject,
  5732. isUndefined: isUndefined,
  5733. isDate: isDate,
  5734. isFile: isFile,
  5735. isBlob: isBlob,
  5736. isFunction: isFunction,
  5737. isStream: isStream,
  5738. isURLSearchParams: isURLSearchParams,
  5739. isStandardBrowserEnv: isStandardBrowserEnv,
  5740. forEach: forEach,
  5741. merge: merge,
  5742. extend: extend,
  5743. trim: trim,
  5744. stripBOM: stripBOM,
  5745. inherits: inherits,
  5746. toFlatObject: toFlatObject,
  5747. kindOf: kindOf,
  5748. kindOfTest: kindOfTest,
  5749. endsWith: endsWith,
  5750. toArray: toArray,
  5751. isTypedArray: isTypedArray,
  5752. isFileList: isFileList
  5753. };
  5754. function encode(val) {
  5755. return encodeURIComponent(val).
  5756. replace(/%3A/gi, ':').
  5757. replace(/%24/g, '$').
  5758. replace(/%2C/gi, ',').
  5759. replace(/%20/g, '+').
  5760. replace(/%5B/gi, '[').
  5761. replace(/%5D/gi, ']');
  5762. }
  5763. /**
  5764. * Build a URL by appending params to the end
  5765. *
  5766. * @param {string} url The base of the url (e.g., http://www.google.com)
  5767. * @param {object} [params] The params to be appended
  5768. * @returns {string} The formatted url
  5769. */
  5770. var buildURL = function buildURL(url, params, paramsSerializer) {
  5771. /*eslint no-param-reassign:0*/
  5772. if (!params) {
  5773. return url;
  5774. }
  5775. var serializedParams;
  5776. if (paramsSerializer) {
  5777. serializedParams = paramsSerializer(params);
  5778. } else if (utils.isURLSearchParams(params)) {
  5779. serializedParams = params.toString();
  5780. } else {
  5781. var parts = [];
  5782. utils.forEach(params, function serialize(val, key) {
  5783. if (val === null || typeof val === 'undefined') {
  5784. return;
  5785. }
  5786. if (utils.isArray(val)) {
  5787. key = key + '[]';
  5788. } else {
  5789. val = [val];
  5790. }
  5791. utils.forEach(val, function parseValue(v) {
  5792. if (utils.isDate(v)) {
  5793. v = v.toISOString();
  5794. } else if (utils.isObject(v)) {
  5795. v = JSON.stringify(v);
  5796. }
  5797. parts.push(encode(key) + '=' + encode(v));
  5798. });
  5799. });
  5800. serializedParams = parts.join('&');
  5801. }
  5802. if (serializedParams) {
  5803. var hashmarkIndex = url.indexOf('#');
  5804. if (hashmarkIndex !== -1) {
  5805. url = url.slice(0, hashmarkIndex);
  5806. }
  5807. url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams;
  5808. }
  5809. return url;
  5810. };
  5811. function InterceptorManager() {
  5812. this.handlers = [];
  5813. }
  5814. /**
  5815. * Add a new interceptor to the stack
  5816. *
  5817. * @param {Function} fulfilled The function to handle `then` for a `Promise`
  5818. * @param {Function} rejected The function to handle `reject` for a `Promise`
  5819. *
  5820. * @return {Number} An ID used to remove interceptor later
  5821. */
  5822. InterceptorManager.prototype.use = function use(fulfilled, rejected, options) {
  5823. this.handlers.push({
  5824. fulfilled: fulfilled,
  5825. rejected: rejected,
  5826. synchronous: options ? options.synchronous : false,
  5827. runWhen: options ? options.runWhen : null
  5828. });
  5829. return this.handlers.length - 1;
  5830. };
  5831. /**
  5832. * Remove an interceptor from the stack
  5833. *
  5834. * @param {Number} id The ID that was returned by `use`
  5835. */
  5836. InterceptorManager.prototype.eject = function eject(id) {
  5837. if (this.handlers[id]) {
  5838. this.handlers[id] = null;
  5839. }
  5840. };
  5841. /**
  5842. * Iterate over all the registered interceptors
  5843. *
  5844. * This method is particularly useful for skipping over any
  5845. * interceptors that may have become `null` calling `eject`.
  5846. *
  5847. * @param {Function} fn The function to call for each interceptor
  5848. */
  5849. InterceptorManager.prototype.forEach = function forEach(fn) {
  5850. utils.forEach(this.handlers, function forEachHandler(h) {
  5851. if (h !== null) {
  5852. fn(h);
  5853. }
  5854. });
  5855. };
  5856. var InterceptorManager_1 = InterceptorManager;
  5857. var normalizeHeaderName = function normalizeHeaderName(headers, normalizedName) {
  5858. utils.forEach(headers, function processHeader(value, name) {
  5859. if (name !== normalizedName && name.toUpperCase() === normalizedName.toUpperCase()) {
  5860. headers[normalizedName] = value;
  5861. delete headers[name];
  5862. }
  5863. });
  5864. };
  5865. /**
  5866. * Create an Error with the specified message, config, error code, request and response.
  5867. *
  5868. * @param {string} message The error message.
  5869. * @param {string} [code] The error code (for example, 'ECONNABORTED').
  5870. * @param {Object} [config] The config.
  5871. * @param {Object} [request] The request.
  5872. * @param {Object} [response] The response.
  5873. * @returns {Error} The created error.
  5874. */
  5875. function AxiosError(message, code, config, request, response) {
  5876. Error.call(this);
  5877. this.message = message;
  5878. this.name = 'AxiosError';
  5879. code && (this.code = code);
  5880. config && (this.config = config);
  5881. request && (this.request = request);
  5882. response && (this.response = response);
  5883. }
  5884. utils.inherits(AxiosError, Error, {
  5885. toJSON: function toJSON() {
  5886. return {
  5887. // Standard
  5888. message: this.message,
  5889. name: this.name,
  5890. // Microsoft
  5891. description: this.description,
  5892. number: this.number,
  5893. // Mozilla
  5894. fileName: this.fileName,
  5895. lineNumber: this.lineNumber,
  5896. columnNumber: this.columnNumber,
  5897. stack: this.stack,
  5898. // Axios
  5899. config: this.config,
  5900. code: this.code,
  5901. status: this.response && this.response.status ? this.response.status : null
  5902. };
  5903. }
  5904. });
  5905. var prototype = AxiosError.prototype;
  5906. var descriptors = {};
  5907. [
  5908. 'ERR_BAD_OPTION_VALUE',
  5909. 'ERR_BAD_OPTION',
  5910. 'ECONNABORTED',
  5911. 'ETIMEDOUT',
  5912. 'ERR_NETWORK',
  5913. 'ERR_FR_TOO_MANY_REDIRECTS',
  5914. 'ERR_DEPRECATED',
  5915. 'ERR_BAD_RESPONSE',
  5916. 'ERR_BAD_REQUEST',
  5917. 'ERR_CANCELED'
  5918. // eslint-disable-next-line func-names
  5919. ].forEach(function(code) {
  5920. descriptors[code] = {value: code};
  5921. });
  5922. Object.defineProperties(AxiosError, descriptors);
  5923. Object.defineProperty(prototype, 'isAxiosError', {value: true});
  5924. // eslint-disable-next-line func-names
  5925. AxiosError.from = function(error, code, config, request, response, customProps) {
  5926. var axiosError = Object.create(prototype);
  5927. utils.toFlatObject(error, axiosError, function filter(obj) {
  5928. return obj !== Error.prototype;
  5929. });
  5930. AxiosError.call(axiosError, error.message, code, config, request, response);
  5931. axiosError.name = error.name;
  5932. customProps && Object.assign(axiosError, customProps);
  5933. return axiosError;
  5934. };
  5935. var AxiosError_1 = AxiosError;
  5936. var transitional = {
  5937. silentJSONParsing: true,
  5938. forcedJSONParsing: true,
  5939. clarifyTimeoutError: false
  5940. };
  5941. /**
  5942. * Convert a data object to FormData
  5943. * @param {Object} obj
  5944. * @param {?Object} [formData]
  5945. * @returns {Object}
  5946. **/
  5947. function toFormData(obj, formData) {
  5948. // eslint-disable-next-line no-param-reassign
  5949. formData = formData || new FormData();
  5950. var stack = [];
  5951. function convertValue(value) {
  5952. if (value === null) return '';
  5953. if (utils.isDate(value)) {
  5954. return value.toISOString();
  5955. }
  5956. if (utils.isArrayBuffer(value) || utils.isTypedArray(value)) {
  5957. return typeof Blob === 'function' ? new Blob([value]) : Buffer.from(value);
  5958. }
  5959. return value;
  5960. }
  5961. function build(data, parentKey) {
  5962. if (utils.isPlainObject(data) || utils.isArray(data)) {
  5963. if (stack.indexOf(data) !== -1) {
  5964. throw Error('Circular reference detected in ' + parentKey);
  5965. }
  5966. stack.push(data);
  5967. utils.forEach(data, function each(value, key) {
  5968. if (utils.isUndefined(value)) return;
  5969. var fullKey = parentKey ? parentKey + '.' + key : key;
  5970. var arr;
  5971. if (value && !parentKey && typeof value === 'object') {
  5972. if (utils.endsWith(key, '{}')) {
  5973. // eslint-disable-next-line no-param-reassign
  5974. value = JSON.stringify(value);
  5975. } else if (utils.endsWith(key, '[]') && (arr = utils.toArray(value))) {
  5976. // eslint-disable-next-line func-names
  5977. arr.forEach(function(el) {
  5978. !utils.isUndefined(el) && formData.append(fullKey, convertValue(el));
  5979. });
  5980. return;
  5981. }
  5982. }
  5983. build(value, fullKey);
  5984. });
  5985. stack.pop();
  5986. } else {
  5987. formData.append(parentKey, convertValue(data));
  5988. }
  5989. }
  5990. build(obj);
  5991. return formData;
  5992. }
  5993. var toFormData_1 = toFormData;
  5994. /**
  5995. * Resolve or reject a Promise based on response status.
  5996. *
  5997. * @param {Function} resolve A function that resolves the promise.
  5998. * @param {Function} reject A function that rejects the promise.
  5999. * @param {object} response The response.
  6000. */
  6001. var settle = function settle(resolve, reject, response) {
  6002. var validateStatus = response.config.validateStatus;
  6003. if (!response.status || !validateStatus || validateStatus(response.status)) {
  6004. resolve(response);
  6005. } else {
  6006. reject(new AxiosError_1(
  6007. 'Request failed with status code ' + response.status,
  6008. [AxiosError_1.ERR_BAD_REQUEST, AxiosError_1.ERR_BAD_RESPONSE][Math.floor(response.status / 100) - 4],
  6009. response.config,
  6010. response.request,
  6011. response
  6012. ));
  6013. }
  6014. };
  6015. var cookies = (
  6016. utils.isStandardBrowserEnv() ?
  6017. // Standard browser envs support document.cookie
  6018. (function standardBrowserEnv() {
  6019. return {
  6020. write: function write(name, value, expires, path, domain, secure) {
  6021. var cookie = [];
  6022. cookie.push(name + '=' + encodeURIComponent(value));
  6023. if (utils.isNumber(expires)) {
  6024. cookie.push('expires=' + new Date(expires).toGMTString());
  6025. }
  6026. if (utils.isString(path)) {
  6027. cookie.push('path=' + path);
  6028. }
  6029. if (utils.isString(domain)) {
  6030. cookie.push('domain=' + domain);
  6031. }
  6032. if (secure === true) {
  6033. cookie.push('secure');
  6034. }
  6035. document.cookie = cookie.join('; ');
  6036. },
  6037. read: function read(name) {
  6038. var match = document.cookie.match(new RegExp('(^|;\\s*)(' + name + ')=([^;]*)'));
  6039. return (match ? decodeURIComponent(match[3]) : null);
  6040. },
  6041. remove: function remove(name) {
  6042. this.write(name, '', Date.now() - 86400000);
  6043. }
  6044. };
  6045. })() :
  6046. // Non standard browser env (web workers, react-native) lack needed support.
  6047. (function nonStandardBrowserEnv() {
  6048. return {
  6049. write: function write() {},
  6050. read: function read() { return null; },
  6051. remove: function remove() {}
  6052. };
  6053. })()
  6054. );
  6055. /**
  6056. * Determines whether the specified URL is absolute
  6057. *
  6058. * @param {string} url The URL to test
  6059. * @returns {boolean} True if the specified URL is absolute, otherwise false
  6060. */
  6061. var isAbsoluteURL = function isAbsoluteURL(url) {
  6062. // A URL is considered absolute if it begins with "<scheme>://" or "//" (protocol-relative URL).
  6063. // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed
  6064. // by any combination of letters, digits, plus, period, or hyphen.
  6065. return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url);
  6066. };
  6067. /**
  6068. * Creates a new URL by combining the specified URLs
  6069. *
  6070. * @param {string} baseURL The base URL
  6071. * @param {string} relativeURL The relative URL
  6072. * @returns {string} The combined URL
  6073. */
  6074. var combineURLs = function combineURLs(baseURL, relativeURL) {
  6075. return relativeURL
  6076. ? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '')
  6077. : baseURL;
  6078. };
  6079. /**
  6080. * Creates a new URL by combining the baseURL with the requestedURL,
  6081. * only when the requestedURL is not already an absolute URL.
  6082. * If the requestURL is absolute, this function returns the requestedURL untouched.
  6083. *
  6084. * @param {string} baseURL The base URL
  6085. * @param {string} requestedURL Absolute or relative URL to combine
  6086. * @returns {string} The combined full path
  6087. */
  6088. var buildFullPath = function buildFullPath(baseURL, requestedURL) {
  6089. if (baseURL && !isAbsoluteURL(requestedURL)) {
  6090. return combineURLs(baseURL, requestedURL);
  6091. }
  6092. return requestedURL;
  6093. };
  6094. // Headers whose duplicates are ignored by node
  6095. // c.f. https://nodejs.org/api/http.html#http_message_headers
  6096. var ignoreDuplicateOf = [
  6097. 'age', 'authorization', 'content-length', 'content-type', 'etag',
  6098. 'expires', 'from', 'host', 'if-modified-since', 'if-unmodified-since',
  6099. 'last-modified', 'location', 'max-forwards', 'proxy-authorization',
  6100. 'referer', 'retry-after', 'user-agent'
  6101. ];
  6102. /**
  6103. * Parse headers into an object
  6104. *
  6105. * ```
  6106. * Date: Wed, 27 Aug 2014 08:58:49 GMT
  6107. * Content-Type: application/json
  6108. * Connection: keep-alive
  6109. * Transfer-Encoding: chunked
  6110. * ```
  6111. *
  6112. * @param {String} headers Headers needing to be parsed
  6113. * @returns {Object} Headers parsed into an object
  6114. */
  6115. var parseHeaders = function parseHeaders(headers) {
  6116. var parsed = {};
  6117. var key;
  6118. var val;
  6119. var i;
  6120. if (!headers) { return parsed; }
  6121. utils.forEach(headers.split('\n'), function parser(line) {
  6122. i = line.indexOf(':');
  6123. key = utils.trim(line.substr(0, i)).toLowerCase();
  6124. val = utils.trim(line.substr(i + 1));
  6125. if (key) {
  6126. if (parsed[key] && ignoreDuplicateOf.indexOf(key) >= 0) {
  6127. return;
  6128. }
  6129. if (key === 'set-cookie') {
  6130. parsed[key] = (parsed[key] ? parsed[key] : []).concat([val]);
  6131. } else {
  6132. parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;
  6133. }
  6134. }
  6135. });
  6136. return parsed;
  6137. };
  6138. var isURLSameOrigin = (
  6139. utils.isStandardBrowserEnv() ?
  6140. // Standard browser envs have full support of the APIs needed to test
  6141. // whether the request URL is of the same origin as current location.
  6142. (function standardBrowserEnv() {
  6143. var msie = /(msie|trident)/i.test(navigator.userAgent);
  6144. var urlParsingNode = document.createElement('a');
  6145. var originURL;
  6146. /**
  6147. * Parse a URL to discover it's components
  6148. *
  6149. * @param {String} url The URL to be parsed
  6150. * @returns {Object}
  6151. */
  6152. function resolveURL(url) {
  6153. var href = url;
  6154. if (msie) {
  6155. // IE needs attribute set twice to normalize properties
  6156. urlParsingNode.setAttribute('href', href);
  6157. href = urlParsingNode.href;
  6158. }
  6159. urlParsingNode.setAttribute('href', href);
  6160. // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils
  6161. return {
  6162. href: urlParsingNode.href,
  6163. protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',
  6164. host: urlParsingNode.host,
  6165. search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '',
  6166. hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',
  6167. hostname: urlParsingNode.hostname,
  6168. port: urlParsingNode.port,
  6169. pathname: (urlParsingNode.pathname.charAt(0) === '/') ?
  6170. urlParsingNode.pathname :
  6171. '/' + urlParsingNode.pathname
  6172. };
  6173. }
  6174. originURL = resolveURL(window.location.href);
  6175. /**
  6176. * Determine if a URL shares the same origin as the current location
  6177. *
  6178. * @param {String} requestURL The URL to test
  6179. * @returns {boolean} True if URL shares the same origin, otherwise false
  6180. */
  6181. return function isURLSameOrigin(requestURL) {
  6182. var parsed = (utils.isString(requestURL)) ? resolveURL(requestURL) : requestURL;
  6183. return (parsed.protocol === originURL.protocol &&
  6184. parsed.host === originURL.host);
  6185. };
  6186. })() :
  6187. // Non standard browser envs (web workers, react-native) lack needed support.
  6188. (function nonStandardBrowserEnv() {
  6189. return function isURLSameOrigin() {
  6190. return true;
  6191. };
  6192. })()
  6193. );
  6194. /**
  6195. * A `CanceledError` is an object that is thrown when an operation is canceled.
  6196. *
  6197. * @class
  6198. * @param {string=} message The message.
  6199. */
  6200. function CanceledError(message) {
  6201. // eslint-disable-next-line no-eq-null,eqeqeq
  6202. AxiosError_1.call(this, message == null ? 'canceled' : message, AxiosError_1.ERR_CANCELED);
  6203. this.name = 'CanceledError';
  6204. }
  6205. utils.inherits(CanceledError, AxiosError_1, {
  6206. __CANCEL__: true
  6207. });
  6208. var CanceledError_1 = CanceledError;
  6209. var parseProtocol = function parseProtocol(url) {
  6210. var match = /^([-+\w]{1,25})(:?\/\/|:)/.exec(url);
  6211. return match && match[1] || '';
  6212. };
  6213. var xhr = function xhrAdapter(config) {
  6214. return new Promise(function dispatchXhrRequest(resolve, reject) {
  6215. var requestData = config.data;
  6216. var requestHeaders = config.headers;
  6217. var responseType = config.responseType;
  6218. var onCanceled;
  6219. function done() {
  6220. if (config.cancelToken) {
  6221. config.cancelToken.unsubscribe(onCanceled);
  6222. }
  6223. if (config.signal) {
  6224. config.signal.removeEventListener('abort', onCanceled);
  6225. }
  6226. }
  6227. if (utils.isFormData(requestData) && utils.isStandardBrowserEnv()) {
  6228. delete requestHeaders['Content-Type']; // Let the browser set it
  6229. }
  6230. var request = new XMLHttpRequest();
  6231. // HTTP basic authentication
  6232. if (config.auth) {
  6233. var username = config.auth.username || '';
  6234. var password = config.auth.password ? unescape(encodeURIComponent(config.auth.password)) : '';
  6235. requestHeaders.Authorization = 'Basic ' + btoa(username + ':' + password);
  6236. }
  6237. var fullPath = buildFullPath(config.baseURL, config.url);
  6238. request.open(config.method.toUpperCase(), buildURL(fullPath, config.params, config.paramsSerializer), true);
  6239. // Set the request timeout in MS
  6240. request.timeout = config.timeout;
  6241. function onloadend() {
  6242. if (!request) {
  6243. return;
  6244. }
  6245. // Prepare the response
  6246. var responseHeaders = 'getAllResponseHeaders' in request ? parseHeaders(request.getAllResponseHeaders()) : null;
  6247. var responseData = !responseType || responseType === 'text' || responseType === 'json' ?
  6248. request.responseText : request.response;
  6249. var response = {
  6250. data: responseData,
  6251. status: request.status,
  6252. statusText: request.statusText,
  6253. headers: responseHeaders,
  6254. config: config,
  6255. request: request
  6256. };
  6257. settle(function _resolve(value) {
  6258. resolve(value);
  6259. done();
  6260. }, function _reject(err) {
  6261. reject(err);
  6262. done();
  6263. }, response);
  6264. // Clean up request
  6265. request = null;
  6266. }
  6267. if ('onloadend' in request) {
  6268. // Use onloadend if available
  6269. request.onloadend = onloadend;
  6270. } else {
  6271. // Listen for ready state to emulate onloadend
  6272. request.onreadystatechange = function handleLoad() {
  6273. if (!request || request.readyState !== 4) {
  6274. return;
  6275. }
  6276. // The request errored out and we didn't get a response, this will be
  6277. // handled by onerror instead
  6278. // With one exception: request that using file: protocol, most browsers
  6279. // will return status as 0 even though it's a successful request
  6280. if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) {
  6281. return;
  6282. }
  6283. // readystate handler is calling before onerror or ontimeout handlers,
  6284. // so we should call onloadend on the next 'tick'
  6285. setTimeout(onloadend);
  6286. };
  6287. }
  6288. // Handle browser request cancellation (as opposed to a manual cancellation)
  6289. request.onabort = function handleAbort() {
  6290. if (!request) {
  6291. return;
  6292. }
  6293. reject(new AxiosError_1('Request aborted', AxiosError_1.ECONNABORTED, config, request));
  6294. // Clean up request
  6295. request = null;
  6296. };
  6297. // Handle low level network errors
  6298. request.onerror = function handleError() {
  6299. // Real errors are hidden from us by the browser
  6300. // onerror should only fire if it's a network error
  6301. reject(new AxiosError_1('Network Error', AxiosError_1.ERR_NETWORK, config, request, request));
  6302. // Clean up request
  6303. request = null;
  6304. };
  6305. // Handle timeout
  6306. request.ontimeout = function handleTimeout() {
  6307. var timeoutErrorMessage = config.timeout ? 'timeout of ' + config.timeout + 'ms exceeded' : 'timeout exceeded';
  6308. var transitional$1 = config.transitional || transitional;
  6309. if (config.timeoutErrorMessage) {
  6310. timeoutErrorMessage = config.timeoutErrorMessage;
  6311. }
  6312. reject(new AxiosError_1(
  6313. timeoutErrorMessage,
  6314. transitional$1.clarifyTimeoutError ? AxiosError_1.ETIMEDOUT : AxiosError_1.ECONNABORTED,
  6315. config,
  6316. request));
  6317. // Clean up request
  6318. request = null;
  6319. };
  6320. // Add xsrf header
  6321. // This is only done if running in a standard browser environment.
  6322. // Specifically not if we're in a web worker, or react-native.
  6323. if (utils.isStandardBrowserEnv()) {
  6324. // Add xsrf header
  6325. var xsrfValue = (config.withCredentials || isURLSameOrigin(fullPath)) && config.xsrfCookieName ?
  6326. cookies.read(config.xsrfCookieName) :
  6327. undefined;
  6328. if (xsrfValue) {
  6329. requestHeaders[config.xsrfHeaderName] = xsrfValue;
  6330. }
  6331. }
  6332. // Add headers to the request
  6333. if ('setRequestHeader' in request) {
  6334. utils.forEach(requestHeaders, function setRequestHeader(val, key) {
  6335. if (typeof requestData === 'undefined' && key.toLowerCase() === 'content-type') {
  6336. // Remove Content-Type if data is undefined
  6337. delete requestHeaders[key];
  6338. } else {
  6339. // Otherwise add header to the request
  6340. request.setRequestHeader(key, val);
  6341. }
  6342. });
  6343. }
  6344. // Add withCredentials to request if needed
  6345. if (!utils.isUndefined(config.withCredentials)) {
  6346. request.withCredentials = !!config.withCredentials;
  6347. }
  6348. // Add responseType to request if needed
  6349. if (responseType && responseType !== 'json') {
  6350. request.responseType = config.responseType;
  6351. }
  6352. // Handle progress if needed
  6353. if (typeof config.onDownloadProgress === 'function') {
  6354. request.addEventListener('progress', config.onDownloadProgress);
  6355. }
  6356. // Not all browsers support upload events
  6357. if (typeof config.onUploadProgress === 'function' && request.upload) {
  6358. request.upload.addEventListener('progress', config.onUploadProgress);
  6359. }
  6360. if (config.cancelToken || config.signal) {
  6361. // Handle cancellation
  6362. // eslint-disable-next-line func-names
  6363. onCanceled = function(cancel) {
  6364. if (!request) {
  6365. return;
  6366. }
  6367. reject(!cancel || (cancel && cancel.type) ? new CanceledError_1() : cancel);
  6368. request.abort();
  6369. request = null;
  6370. };
  6371. config.cancelToken && config.cancelToken.subscribe(onCanceled);
  6372. if (config.signal) {
  6373. config.signal.aborted ? onCanceled() : config.signal.addEventListener('abort', onCanceled);
  6374. }
  6375. }
  6376. if (!requestData) {
  6377. requestData = null;
  6378. }
  6379. var protocol = parseProtocol(fullPath);
  6380. if (protocol && [ 'http', 'https', 'file' ].indexOf(protocol) === -1) {
  6381. reject(new AxiosError_1('Unsupported protocol ' + protocol + ':', AxiosError_1.ERR_BAD_REQUEST, config));
  6382. return;
  6383. }
  6384. // Send the request
  6385. request.send(requestData);
  6386. });
  6387. };
  6388. // eslint-disable-next-line strict
  6389. var _null = null;
  6390. var DEFAULT_CONTENT_TYPE = {
  6391. 'Content-Type': 'application/x-www-form-urlencoded'
  6392. };
  6393. function setContentTypeIfUnset(headers, value) {
  6394. if (!utils.isUndefined(headers) && utils.isUndefined(headers['Content-Type'])) {
  6395. headers['Content-Type'] = value;
  6396. }
  6397. }
  6398. function getDefaultAdapter() {
  6399. var adapter;
  6400. if (typeof XMLHttpRequest !== 'undefined') {
  6401. // For browsers use XHR adapter
  6402. adapter = xhr;
  6403. } else if (typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]') {
  6404. // For node use HTTP adapter
  6405. adapter = xhr;
  6406. }
  6407. return adapter;
  6408. }
  6409. function stringifySafely(rawValue, parser, encoder) {
  6410. if (utils.isString(rawValue)) {
  6411. try {
  6412. (parser || JSON.parse)(rawValue);
  6413. return utils.trim(rawValue);
  6414. } catch (e) {
  6415. if (e.name !== 'SyntaxError') {
  6416. throw e;
  6417. }
  6418. }
  6419. }
  6420. return (encoder || JSON.stringify)(rawValue);
  6421. }
  6422. var defaults = {
  6423. transitional: transitional,
  6424. adapter: getDefaultAdapter(),
  6425. transformRequest: [function transformRequest(data, headers) {
  6426. normalizeHeaderName(headers, 'Accept');
  6427. normalizeHeaderName(headers, 'Content-Type');
  6428. if (utils.isFormData(data) ||
  6429. utils.isArrayBuffer(data) ||
  6430. utils.isBuffer(data) ||
  6431. utils.isStream(data) ||
  6432. utils.isFile(data) ||
  6433. utils.isBlob(data)
  6434. ) {
  6435. return data;
  6436. }
  6437. if (utils.isArrayBufferView(data)) {
  6438. return data.buffer;
  6439. }
  6440. if (utils.isURLSearchParams(data)) {
  6441. setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8');
  6442. return data.toString();
  6443. }
  6444. var isObjectPayload = utils.isObject(data);
  6445. var contentType = headers && headers['Content-Type'];
  6446. var isFileList;
  6447. if ((isFileList = utils.isFileList(data)) || (isObjectPayload && contentType === 'multipart/form-data')) {
  6448. var _FormData = this.env && this.env.FormData;
  6449. return toFormData_1(isFileList ? {'files[]': data} : data, _FormData && new _FormData());
  6450. } else if (isObjectPayload || contentType === 'application/json') {
  6451. setContentTypeIfUnset(headers, 'application/json');
  6452. return stringifySafely(data);
  6453. }
  6454. return data;
  6455. }],
  6456. transformResponse: [function transformResponse(data) {
  6457. var transitional = this.transitional || defaults.transitional;
  6458. var silentJSONParsing = transitional && transitional.silentJSONParsing;
  6459. var forcedJSONParsing = transitional && transitional.forcedJSONParsing;
  6460. var strictJSONParsing = !silentJSONParsing && this.responseType === 'json';
  6461. if (strictJSONParsing || (forcedJSONParsing && utils.isString(data) && data.length)) {
  6462. try {
  6463. return JSON.parse(data);
  6464. } catch (e) {
  6465. if (strictJSONParsing) {
  6466. if (e.name === 'SyntaxError') {
  6467. throw AxiosError_1.from(e, AxiosError_1.ERR_BAD_RESPONSE, this, null, this.response);
  6468. }
  6469. throw e;
  6470. }
  6471. }
  6472. }
  6473. return data;
  6474. }],
  6475. /**
  6476. * A timeout in milliseconds to abort a request. If set to 0 (default) a
  6477. * timeout is not created.
  6478. */
  6479. timeout: 0,
  6480. xsrfCookieName: 'XSRF-TOKEN',
  6481. xsrfHeaderName: 'X-XSRF-TOKEN',
  6482. maxContentLength: -1,
  6483. maxBodyLength: -1,
  6484. env: {
  6485. FormData: _null
  6486. },
  6487. validateStatus: function validateStatus(status) {
  6488. return status >= 200 && status < 300;
  6489. },
  6490. headers: {
  6491. common: {
  6492. 'Accept': 'application/json, text/plain, */*'
  6493. }
  6494. }
  6495. };
  6496. utils.forEach(['delete', 'get', 'head'], function forEachMethodNoData(method) {
  6497. defaults.headers[method] = {};
  6498. });
  6499. utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
  6500. defaults.headers[method] = utils.merge(DEFAULT_CONTENT_TYPE);
  6501. });
  6502. var defaults_1 = defaults;
  6503. /**
  6504. * Transform the data for a request or a response
  6505. *
  6506. * @param {Object|String} data The data to be transformed
  6507. * @param {Array} headers The headers for the request or response
  6508. * @param {Array|Function} fns A single function or Array of functions
  6509. * @returns {*} The resulting transformed data
  6510. */
  6511. var transformData = function transformData(data, headers, fns) {
  6512. var context = this || defaults_1;
  6513. /*eslint no-param-reassign:0*/
  6514. utils.forEach(fns, function transform(fn) {
  6515. data = fn.call(context, data, headers);
  6516. });
  6517. return data;
  6518. };
  6519. var isCancel = function isCancel(value) {
  6520. return !!(value && value.__CANCEL__);
  6521. };
  6522. /**
  6523. * Throws a `CanceledError` if cancellation has been requested.
  6524. */
  6525. function throwIfCancellationRequested(config) {
  6526. if (config.cancelToken) {
  6527. config.cancelToken.throwIfRequested();
  6528. }
  6529. if (config.signal && config.signal.aborted) {
  6530. throw new CanceledError_1();
  6531. }
  6532. }
  6533. /**
  6534. * Dispatch a request to the server using the configured adapter.
  6535. *
  6536. * @param {object} config The config that is to be used for the request
  6537. * @returns {Promise} The Promise to be fulfilled
  6538. */
  6539. var dispatchRequest = function dispatchRequest(config) {
  6540. throwIfCancellationRequested(config);
  6541. // Ensure headers exist
  6542. config.headers = config.headers || {};
  6543. // Transform request data
  6544. config.data = transformData.call(
  6545. config,
  6546. config.data,
  6547. config.headers,
  6548. config.transformRequest
  6549. );
  6550. // Flatten headers
  6551. config.headers = utils.merge(
  6552. config.headers.common || {},
  6553. config.headers[config.method] || {},
  6554. config.headers
  6555. );
  6556. utils.forEach(
  6557. ['delete', 'get', 'head', 'post', 'put', 'patch', 'common'],
  6558. function cleanHeaderConfig(method) {
  6559. delete config.headers[method];
  6560. }
  6561. );
  6562. var adapter = config.adapter || defaults_1.adapter;
  6563. return adapter(config).then(function onAdapterResolution(response) {
  6564. throwIfCancellationRequested(config);
  6565. // Transform response data
  6566. response.data = transformData.call(
  6567. config,
  6568. response.data,
  6569. response.headers,
  6570. config.transformResponse
  6571. );
  6572. return response;
  6573. }, function onAdapterRejection(reason) {
  6574. if (!isCancel(reason)) {
  6575. throwIfCancellationRequested(config);
  6576. // Transform response data
  6577. if (reason && reason.response) {
  6578. reason.response.data = transformData.call(
  6579. config,
  6580. reason.response.data,
  6581. reason.response.headers,
  6582. config.transformResponse
  6583. );
  6584. }
  6585. }
  6586. return Promise.reject(reason);
  6587. });
  6588. };
  6589. /**
  6590. * Config-specific merge-function which creates a new config-object
  6591. * by merging two configuration objects together.
  6592. *
  6593. * @param {Object} config1
  6594. * @param {Object} config2
  6595. * @returns {Object} New object resulting from merging config2 to config1
  6596. */
  6597. var mergeConfig = function mergeConfig(config1, config2) {
  6598. // eslint-disable-next-line no-param-reassign
  6599. config2 = config2 || {};
  6600. var config = {};
  6601. function getMergedValue(target, source) {
  6602. if (utils.isPlainObject(target) && utils.isPlainObject(source)) {
  6603. return utils.merge(target, source);
  6604. } else if (utils.isPlainObject(source)) {
  6605. return utils.merge({}, source);
  6606. } else if (utils.isArray(source)) {
  6607. return source.slice();
  6608. }
  6609. return source;
  6610. }
  6611. // eslint-disable-next-line consistent-return
  6612. function mergeDeepProperties(prop) {
  6613. if (!utils.isUndefined(config2[prop])) {
  6614. return getMergedValue(config1[prop], config2[prop]);
  6615. } else if (!utils.isUndefined(config1[prop])) {
  6616. return getMergedValue(undefined, config1[prop]);
  6617. }
  6618. }
  6619. // eslint-disable-next-line consistent-return
  6620. function valueFromConfig2(prop) {
  6621. if (!utils.isUndefined(config2[prop])) {
  6622. return getMergedValue(undefined, config2[prop]);
  6623. }
  6624. }
  6625. // eslint-disable-next-line consistent-return
  6626. function defaultToConfig2(prop) {
  6627. if (!utils.isUndefined(config2[prop])) {
  6628. return getMergedValue(undefined, config2[prop]);
  6629. } else if (!utils.isUndefined(config1[prop])) {
  6630. return getMergedValue(undefined, config1[prop]);
  6631. }
  6632. }
  6633. // eslint-disable-next-line consistent-return
  6634. function mergeDirectKeys(prop) {
  6635. if (prop in config2) {
  6636. return getMergedValue(config1[prop], config2[prop]);
  6637. } else if (prop in config1) {
  6638. return getMergedValue(undefined, config1[prop]);
  6639. }
  6640. }
  6641. var mergeMap = {
  6642. 'url': valueFromConfig2,
  6643. 'method': valueFromConfig2,
  6644. 'data': valueFromConfig2,
  6645. 'baseURL': defaultToConfig2,
  6646. 'transformRequest': defaultToConfig2,
  6647. 'transformResponse': defaultToConfig2,
  6648. 'paramsSerializer': defaultToConfig2,
  6649. 'timeout': defaultToConfig2,
  6650. 'timeoutMessage': defaultToConfig2,
  6651. 'withCredentials': defaultToConfig2,
  6652. 'adapter': defaultToConfig2,
  6653. 'responseType': defaultToConfig2,
  6654. 'xsrfCookieName': defaultToConfig2,
  6655. 'xsrfHeaderName': defaultToConfig2,
  6656. 'onUploadProgress': defaultToConfig2,
  6657. 'onDownloadProgress': defaultToConfig2,
  6658. 'decompress': defaultToConfig2,
  6659. 'maxContentLength': defaultToConfig2,
  6660. 'maxBodyLength': defaultToConfig2,
  6661. 'beforeRedirect': defaultToConfig2,
  6662. 'transport': defaultToConfig2,
  6663. 'httpAgent': defaultToConfig2,
  6664. 'httpsAgent': defaultToConfig2,
  6665. 'cancelToken': defaultToConfig2,
  6666. 'socketPath': defaultToConfig2,
  6667. 'responseEncoding': defaultToConfig2,
  6668. 'validateStatus': mergeDirectKeys
  6669. };
  6670. utils.forEach(Object.keys(config1).concat(Object.keys(config2)), function computeConfigValue(prop) {
  6671. var merge = mergeMap[prop] || mergeDeepProperties;
  6672. var configValue = merge(prop);
  6673. (utils.isUndefined(configValue) && merge !== mergeDirectKeys) || (config[prop] = configValue);
  6674. });
  6675. return config;
  6676. };
  6677. var data = {
  6678. "version": "0.27.2"
  6679. };
  6680. var VERSION = data.version;
  6681. var validators$1 = {};
  6682. // eslint-disable-next-line func-names
  6683. ['object', 'boolean', 'number', 'function', 'string', 'symbol'].forEach(function(type, i) {
  6684. validators$1[type] = function validator(thing) {
  6685. return typeof thing === type || 'a' + (i < 1 ? 'n ' : ' ') + type;
  6686. };
  6687. });
  6688. var deprecatedWarnings = {};
  6689. /**
  6690. * Transitional option validator
  6691. * @param {function|boolean?} validator - set to false if the transitional option has been removed
  6692. * @param {string?} version - deprecated version / removed since version
  6693. * @param {string?} message - some message with additional info
  6694. * @returns {function}
  6695. */
  6696. validators$1.transitional = function transitional(validator, version, message) {
  6697. function formatMessage(opt, desc) {
  6698. return '[Axios v' + VERSION + '] Transitional option \'' + opt + '\'' + desc + (message ? '. ' + message : '');
  6699. }
  6700. // eslint-disable-next-line func-names
  6701. return function(value, opt, opts) {
  6702. if (validator === false) {
  6703. throw new AxiosError_1(
  6704. formatMessage(opt, ' has been removed' + (version ? ' in ' + version : '')),
  6705. AxiosError_1.ERR_DEPRECATED
  6706. );
  6707. }
  6708. if (version && !deprecatedWarnings[opt]) {
  6709. deprecatedWarnings[opt] = true;
  6710. // eslint-disable-next-line no-console
  6711. console.warn(
  6712. formatMessage(
  6713. opt,
  6714. ' has been deprecated since v' + version + ' and will be removed in the near future'
  6715. )
  6716. );
  6717. }
  6718. return validator ? validator(value, opt, opts) : true;
  6719. };
  6720. };
  6721. /**
  6722. * Assert object's properties type
  6723. * @param {object} options
  6724. * @param {object} schema
  6725. * @param {boolean?} allowUnknown
  6726. */
  6727. function assertOptions(options, schema, allowUnknown) {
  6728. if (typeof options !== 'object') {
  6729. throw new AxiosError_1('options must be an object', AxiosError_1.ERR_BAD_OPTION_VALUE);
  6730. }
  6731. var keys = Object.keys(options);
  6732. var i = keys.length;
  6733. while (i-- > 0) {
  6734. var opt = keys[i];
  6735. var validator = schema[opt];
  6736. if (validator) {
  6737. var value = options[opt];
  6738. var result = value === undefined || validator(value, opt, options);
  6739. if (result !== true) {
  6740. throw new AxiosError_1('option ' + opt + ' must be ' + result, AxiosError_1.ERR_BAD_OPTION_VALUE);
  6741. }
  6742. continue;
  6743. }
  6744. if (allowUnknown !== true) {
  6745. throw new AxiosError_1('Unknown option ' + opt, AxiosError_1.ERR_BAD_OPTION);
  6746. }
  6747. }
  6748. }
  6749. var validator = {
  6750. assertOptions: assertOptions,
  6751. validators: validators$1
  6752. };
  6753. var validators = validator.validators;
  6754. /**
  6755. * Create a new instance of Axios
  6756. *
  6757. * @param {Object} instanceConfig The default config for the instance
  6758. */
  6759. function Axios(instanceConfig) {
  6760. this.defaults = instanceConfig;
  6761. this.interceptors = {
  6762. request: new InterceptorManager_1(),
  6763. response: new InterceptorManager_1()
  6764. };
  6765. }
  6766. /**
  6767. * Dispatch a request
  6768. *
  6769. * @param {Object} config The config specific for this request (merged with this.defaults)
  6770. */
  6771. Axios.prototype.request = function request(configOrUrl, config) {
  6772. /*eslint no-param-reassign:0*/
  6773. // Allow for axios('example/url'[, config]) a la fetch API
  6774. if (typeof configOrUrl === 'string') {
  6775. config = config || {};
  6776. config.url = configOrUrl;
  6777. } else {
  6778. config = configOrUrl || {};
  6779. }
  6780. config = mergeConfig(this.defaults, config);
  6781. // Set config.method
  6782. if (config.method) {
  6783. config.method = config.method.toLowerCase();
  6784. } else if (this.defaults.method) {
  6785. config.method = this.defaults.method.toLowerCase();
  6786. } else {
  6787. config.method = 'get';
  6788. }
  6789. var transitional = config.transitional;
  6790. if (transitional !== undefined) {
  6791. validator.assertOptions(transitional, {
  6792. silentJSONParsing: validators.transitional(validators.boolean),
  6793. forcedJSONParsing: validators.transitional(validators.boolean),
  6794. clarifyTimeoutError: validators.transitional(validators.boolean)
  6795. }, false);
  6796. }
  6797. // filter out skipped interceptors
  6798. var requestInterceptorChain = [];
  6799. var synchronousRequestInterceptors = true;
  6800. this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
  6801. if (typeof interceptor.runWhen === 'function' && interceptor.runWhen(config) === false) {
  6802. return;
  6803. }
  6804. synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous;
  6805. requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected);
  6806. });
  6807. var responseInterceptorChain = [];
  6808. this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
  6809. responseInterceptorChain.push(interceptor.fulfilled, interceptor.rejected);
  6810. });
  6811. var promise;
  6812. if (!synchronousRequestInterceptors) {
  6813. var chain = [dispatchRequest, undefined];
  6814. Array.prototype.unshift.apply(chain, requestInterceptorChain);
  6815. chain = chain.concat(responseInterceptorChain);
  6816. promise = Promise.resolve(config);
  6817. while (chain.length) {
  6818. promise = promise.then(chain.shift(), chain.shift());
  6819. }
  6820. return promise;
  6821. }
  6822. var newConfig = config;
  6823. while (requestInterceptorChain.length) {
  6824. var onFulfilled = requestInterceptorChain.shift();
  6825. var onRejected = requestInterceptorChain.shift();
  6826. try {
  6827. newConfig = onFulfilled(newConfig);
  6828. } catch (error) {
  6829. onRejected(error);
  6830. break;
  6831. }
  6832. }
  6833. try {
  6834. promise = dispatchRequest(newConfig);
  6835. } catch (error) {
  6836. return Promise.reject(error);
  6837. }
  6838. while (responseInterceptorChain.length) {
  6839. promise = promise.then(responseInterceptorChain.shift(), responseInterceptorChain.shift());
  6840. }
  6841. return promise;
  6842. };
  6843. Axios.prototype.getUri = function getUri(config) {
  6844. config = mergeConfig(this.defaults, config);
  6845. var fullPath = buildFullPath(config.baseURL, config.url);
  6846. return buildURL(fullPath, config.params, config.paramsSerializer);
  6847. };
  6848. // Provide aliases for supported request methods
  6849. utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) {
  6850. /*eslint func-names:0*/
  6851. Axios.prototype[method] = function(url, config) {
  6852. return this.request(mergeConfig(config || {}, {
  6853. method: method,
  6854. url: url,
  6855. data: (config || {}).data
  6856. }));
  6857. };
  6858. });
  6859. utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
  6860. /*eslint func-names:0*/
  6861. function generateHTTPMethod(isForm) {
  6862. return function httpMethod(url, data, config) {
  6863. return this.request(mergeConfig(config || {}, {
  6864. method: method,
  6865. headers: isForm ? {
  6866. 'Content-Type': 'multipart/form-data'
  6867. } : {},
  6868. url: url,
  6869. data: data
  6870. }));
  6871. };
  6872. }
  6873. Axios.prototype[method] = generateHTTPMethod();
  6874. Axios.prototype[method + 'Form'] = generateHTTPMethod(true);
  6875. });
  6876. var Axios_1 = Axios;
  6877. /**
  6878. * A `CancelToken` is an object that can be used to request cancellation of an operation.
  6879. *
  6880. * @class
  6881. * @param {Function} executor The executor function.
  6882. */
  6883. function CancelToken(executor) {
  6884. if (typeof executor !== 'function') {
  6885. throw new TypeError('executor must be a function.');
  6886. }
  6887. var resolvePromise;
  6888. this.promise = new Promise(function promiseExecutor(resolve) {
  6889. resolvePromise = resolve;
  6890. });
  6891. var token = this;
  6892. // eslint-disable-next-line func-names
  6893. this.promise.then(function(cancel) {
  6894. if (!token._listeners) return;
  6895. var i;
  6896. var l = token._listeners.length;
  6897. for (i = 0; i < l; i++) {
  6898. token._listeners[i](cancel);
  6899. }
  6900. token._listeners = null;
  6901. });
  6902. // eslint-disable-next-line func-names
  6903. this.promise.then = function(onfulfilled) {
  6904. var _resolve;
  6905. // eslint-disable-next-line func-names
  6906. var promise = new Promise(function(resolve) {
  6907. token.subscribe(resolve);
  6908. _resolve = resolve;
  6909. }).then(onfulfilled);
  6910. promise.cancel = function reject() {
  6911. token.unsubscribe(_resolve);
  6912. };
  6913. return promise;
  6914. };
  6915. executor(function cancel(message) {
  6916. if (token.reason) {
  6917. // Cancellation has already been requested
  6918. return;
  6919. }
  6920. token.reason = new CanceledError_1(message);
  6921. resolvePromise(token.reason);
  6922. });
  6923. }
  6924. /**
  6925. * Throws a `CanceledError` if cancellation has been requested.
  6926. */
  6927. CancelToken.prototype.throwIfRequested = function throwIfRequested() {
  6928. if (this.reason) {
  6929. throw this.reason;
  6930. }
  6931. };
  6932. /**
  6933. * Subscribe to the cancel signal
  6934. */
  6935. CancelToken.prototype.subscribe = function subscribe(listener) {
  6936. if (this.reason) {
  6937. listener(this.reason);
  6938. return;
  6939. }
  6940. if (this._listeners) {
  6941. this._listeners.push(listener);
  6942. } else {
  6943. this._listeners = [listener];
  6944. }
  6945. };
  6946. /**
  6947. * Unsubscribe from the cancel signal
  6948. */
  6949. CancelToken.prototype.unsubscribe = function unsubscribe(listener) {
  6950. if (!this._listeners) {
  6951. return;
  6952. }
  6953. var index = this._listeners.indexOf(listener);
  6954. if (index !== -1) {
  6955. this._listeners.splice(index, 1);
  6956. }
  6957. };
  6958. /**
  6959. * Returns an object that contains a new `CancelToken` and a function that, when called,
  6960. * cancels the `CancelToken`.
  6961. */
  6962. CancelToken.source = function source() {
  6963. var cancel;
  6964. var token = new CancelToken(function executor(c) {
  6965. cancel = c;
  6966. });
  6967. return {
  6968. token: token,
  6969. cancel: cancel
  6970. };
  6971. };
  6972. var CancelToken_1 = CancelToken;
  6973. /**
  6974. * Syntactic sugar for invoking a function and expanding an array for arguments.
  6975. *
  6976. * Common use case would be to use `Function.prototype.apply`.
  6977. *
  6978. * ```js
  6979. * function f(x, y, z) {}
  6980. * var args = [1, 2, 3];
  6981. * f.apply(null, args);
  6982. * ```
  6983. *
  6984. * With `spread` this example can be re-written.
  6985. *
  6986. * ```js
  6987. * spread(function(x, y, z) {})([1, 2, 3]);
  6988. * ```
  6989. *
  6990. * @param {Function} callback
  6991. * @returns {Function}
  6992. */
  6993. var spread = function spread(callback) {
  6994. return function wrap(arr) {
  6995. return callback.apply(null, arr);
  6996. };
  6997. };
  6998. /**
  6999. * Determines whether the payload is an error thrown by Axios
  7000. *
  7001. * @param {*} payload The value to test
  7002. * @returns {boolean} True if the payload is an error thrown by Axios, otherwise false
  7003. */
  7004. var isAxiosError = function isAxiosError(payload) {
  7005. return utils.isObject(payload) && (payload.isAxiosError === true);
  7006. };
  7007. /**
  7008. * Create an instance of Axios
  7009. *
  7010. * @param {Object} defaultConfig The default config for the instance
  7011. * @return {Axios} A new instance of Axios
  7012. */
  7013. function createInstance(defaultConfig) {
  7014. var context = new Axios_1(defaultConfig);
  7015. var instance = bind(Axios_1.prototype.request, context);
  7016. // Copy axios.prototype to instance
  7017. utils.extend(instance, Axios_1.prototype, context);
  7018. // Copy context to instance
  7019. utils.extend(instance, context);
  7020. // Factory for creating new instances
  7021. instance.create = function create(instanceConfig) {
  7022. return createInstance(mergeConfig(defaultConfig, instanceConfig));
  7023. };
  7024. return instance;
  7025. }
  7026. // Create the default instance to be exported
  7027. var axios$1 = createInstance(defaults_1);
  7028. // Expose Axios class to allow class inheritance
  7029. axios$1.Axios = Axios_1;
  7030. // Expose Cancel & CancelToken
  7031. axios$1.CanceledError = CanceledError_1;
  7032. axios$1.CancelToken = CancelToken_1;
  7033. axios$1.isCancel = isCancel;
  7034. axios$1.VERSION = data.version;
  7035. axios$1.toFormData = toFormData_1;
  7036. // Expose AxiosError class
  7037. axios$1.AxiosError = AxiosError_1;
  7038. // alias for CanceledError for backward compatibility
  7039. axios$1.Cancel = axios$1.CanceledError;
  7040. // Expose all/spread
  7041. axios$1.all = function all(promises) {
  7042. return Promise.all(promises);
  7043. };
  7044. axios$1.spread = spread;
  7045. // Expose isAxiosError
  7046. axios$1.isAxiosError = isAxiosError;
  7047. var axios_1 = axios$1;
  7048. // Allow use of default import syntax in TypeScript
  7049. var _default = axios$1;
  7050. axios_1.default = _default;
  7051. var axios = axios_1;
  7052. /*!
  7053. * @overview es6-promise - a tiny implementation of Promises/A+.
  7054. * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald)
  7055. * @license Licensed under MIT license
  7056. * See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE
  7057. * @version v4.2.8+1e68dce6
  7058. */
  7059. var es6Promise = createCommonjsModule(function (module, exports) {
  7060. (function (global, factory) {
  7061. module.exports = factory() ;
  7062. }(commonjsGlobal, (function () {
  7063. function objectOrFunction(x) {
  7064. var type = typeof x;
  7065. return x !== null && (type === 'object' || type === 'function');
  7066. }
  7067. function isFunction(x) {
  7068. return typeof x === 'function';
  7069. }
  7070. var _isArray = void 0;
  7071. if (Array.isArray) {
  7072. _isArray = Array.isArray;
  7073. } else {
  7074. _isArray = function (x) {
  7075. return Object.prototype.toString.call(x) === '[object Array]';
  7076. };
  7077. }
  7078. var isArray = _isArray;
  7079. var len = 0;
  7080. var vertxNext = void 0;
  7081. var customSchedulerFn = void 0;
  7082. var asap = function asap(callback, arg) {
  7083. queue[len] = callback;
  7084. queue[len + 1] = arg;
  7085. len += 2;
  7086. if (len === 2) {
  7087. // If len is 2, that means that we need to schedule an async flush.
  7088. // If additional callbacks are queued before the queue is flushed, they
  7089. // will be processed by this flush that we are scheduling.
  7090. if (customSchedulerFn) {
  7091. customSchedulerFn(flush);
  7092. } else {
  7093. scheduleFlush();
  7094. }
  7095. }
  7096. };
  7097. function setScheduler(scheduleFn) {
  7098. customSchedulerFn = scheduleFn;
  7099. }
  7100. function setAsap(asapFn) {
  7101. asap = asapFn;
  7102. }
  7103. var browserWindow = typeof window !== 'undefined' ? window : undefined;
  7104. var browserGlobal = browserWindow || {};
  7105. var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
  7106. var isNode = typeof self === 'undefined' && typeof process !== 'undefined' && {}.toString.call(process) === '[object process]';
  7107. // test for web worker but not in IE10
  7108. var isWorker = typeof Uint8ClampedArray !== 'undefined' && typeof importScripts !== 'undefined' && typeof MessageChannel !== 'undefined';
  7109. // node
  7110. function useNextTick() {
  7111. // node version 0.10.x displays a deprecation warning when nextTick is used recursively
  7112. // see https://github.com/cujojs/when/issues/410 for details
  7113. return function () {
  7114. return process.nextTick(flush);
  7115. };
  7116. }
  7117. // vertx
  7118. function useVertxTimer() {
  7119. if (typeof vertxNext !== 'undefined') {
  7120. return function () {
  7121. vertxNext(flush);
  7122. };
  7123. }
  7124. return useSetTimeout();
  7125. }
  7126. function useMutationObserver() {
  7127. var iterations = 0;
  7128. var observer = new BrowserMutationObserver(flush);
  7129. var node = document.createTextNode('');
  7130. observer.observe(node, { characterData: true });
  7131. return function () {
  7132. node.data = iterations = ++iterations % 2;
  7133. };
  7134. }
  7135. // web worker
  7136. function useMessageChannel() {
  7137. var channel = new MessageChannel();
  7138. channel.port1.onmessage = flush;
  7139. return function () {
  7140. return channel.port2.postMessage(0);
  7141. };
  7142. }
  7143. function useSetTimeout() {
  7144. // Store setTimeout reference so es6-promise will be unaffected by
  7145. // other code modifying setTimeout (like sinon.useFakeTimers())
  7146. var globalSetTimeout = setTimeout;
  7147. return function () {
  7148. return globalSetTimeout(flush, 1);
  7149. };
  7150. }
  7151. var queue = new Array(1000);
  7152. function flush() {
  7153. for (var i = 0; i < len; i += 2) {
  7154. var callback = queue[i];
  7155. var arg = queue[i + 1];
  7156. callback(arg);
  7157. queue[i] = undefined;
  7158. queue[i + 1] = undefined;
  7159. }
  7160. len = 0;
  7161. }
  7162. function attemptVertx() {
  7163. try {
  7164. var vertx = Function('return this')().require('vertx');
  7165. vertxNext = vertx.runOnLoop || vertx.runOnContext;
  7166. return useVertxTimer();
  7167. } catch (e) {
  7168. return useSetTimeout();
  7169. }
  7170. }
  7171. var scheduleFlush = void 0;
  7172. // Decide what async method to use to triggering processing of queued callbacks:
  7173. if (isNode) {
  7174. scheduleFlush = useNextTick();
  7175. } else if (BrowserMutationObserver) {
  7176. scheduleFlush = useMutationObserver();
  7177. } else if (isWorker) {
  7178. scheduleFlush = useMessageChannel();
  7179. } else if (browserWindow === undefined && typeof commonjsRequire === 'function') {
  7180. scheduleFlush = attemptVertx();
  7181. } else {
  7182. scheduleFlush = useSetTimeout();
  7183. }
  7184. function then(onFulfillment, onRejection) {
  7185. var parent = this;
  7186. var child = new this.constructor(noop);
  7187. if (child[PROMISE_ID] === undefined) {
  7188. makePromise(child);
  7189. }
  7190. var _state = parent._state;
  7191. if (_state) {
  7192. var callback = arguments[_state - 1];
  7193. asap(function () {
  7194. return invokeCallback(_state, child, callback, parent._result);
  7195. });
  7196. } else {
  7197. subscribe(parent, child, onFulfillment, onRejection);
  7198. }
  7199. return child;
  7200. }
  7201. /**
  7202. `Promise.resolve` returns a promise that will become resolved with the
  7203. passed `value`. It is shorthand for the following:
  7204. ```javascript
  7205. let promise = new Promise(function(resolve, reject){
  7206. resolve(1);
  7207. });
  7208. promise.then(function(value){
  7209. // value === 1
  7210. });
  7211. ```
  7212. Instead of writing the above, your code now simply becomes the following:
  7213. ```javascript
  7214. let promise = Promise.resolve(1);
  7215. promise.then(function(value){
  7216. // value === 1
  7217. });
  7218. ```
  7219. @method resolve
  7220. @static
  7221. @param {Any} value value that the returned promise will be resolved with
  7222. Useful for tooling.
  7223. @return {Promise} a promise that will become fulfilled with the given
  7224. `value`
  7225. */
  7226. function resolve$1(object) {
  7227. /*jshint validthis:true */
  7228. var Constructor = this;
  7229. if (object && typeof object === 'object' && object.constructor === Constructor) {
  7230. return object;
  7231. }
  7232. var promise = new Constructor(noop);
  7233. resolve(promise, object);
  7234. return promise;
  7235. }
  7236. var PROMISE_ID = Math.random().toString(36).substring(2);
  7237. function noop() {}
  7238. var PENDING = void 0;
  7239. var FULFILLED = 1;
  7240. var REJECTED = 2;
  7241. function selfFulfillment() {
  7242. return new TypeError("You cannot resolve a promise with itself");
  7243. }
  7244. function cannotReturnOwn() {
  7245. return new TypeError('A promises callback cannot return that same promise.');
  7246. }
  7247. function tryThen(then$$1, value, fulfillmentHandler, rejectionHandler) {
  7248. try {
  7249. then$$1.call(value, fulfillmentHandler, rejectionHandler);
  7250. } catch (e) {
  7251. return e;
  7252. }
  7253. }
  7254. function handleForeignThenable(promise, thenable, then$$1) {
  7255. asap(function (promise) {
  7256. var sealed = false;
  7257. var error = tryThen(then$$1, thenable, function (value) {
  7258. if (sealed) {
  7259. return;
  7260. }
  7261. sealed = true;
  7262. if (thenable !== value) {
  7263. resolve(promise, value);
  7264. } else {
  7265. fulfill(promise, value);
  7266. }
  7267. }, function (reason) {
  7268. if (sealed) {
  7269. return;
  7270. }
  7271. sealed = true;
  7272. reject(promise, reason);
  7273. }, 'Settle: ' + (promise._label || ' unknown promise'));
  7274. if (!sealed && error) {
  7275. sealed = true;
  7276. reject(promise, error);
  7277. }
  7278. }, promise);
  7279. }
  7280. function handleOwnThenable(promise, thenable) {
  7281. if (thenable._state === FULFILLED) {
  7282. fulfill(promise, thenable._result);
  7283. } else if (thenable._state === REJECTED) {
  7284. reject(promise, thenable._result);
  7285. } else {
  7286. subscribe(thenable, undefined, function (value) {
  7287. return resolve(promise, value);
  7288. }, function (reason) {
  7289. return reject(promise, reason);
  7290. });
  7291. }
  7292. }
  7293. function handleMaybeThenable(promise, maybeThenable, then$$1) {
  7294. if (maybeThenable.constructor === promise.constructor && then$$1 === then && maybeThenable.constructor.resolve === resolve$1) {
  7295. handleOwnThenable(promise, maybeThenable);
  7296. } else {
  7297. if (then$$1 === undefined) {
  7298. fulfill(promise, maybeThenable);
  7299. } else if (isFunction(then$$1)) {
  7300. handleForeignThenable(promise, maybeThenable, then$$1);
  7301. } else {
  7302. fulfill(promise, maybeThenable);
  7303. }
  7304. }
  7305. }
  7306. function resolve(promise, value) {
  7307. if (promise === value) {
  7308. reject(promise, selfFulfillment());
  7309. } else if (objectOrFunction(value)) {
  7310. var then$$1 = void 0;
  7311. try {
  7312. then$$1 = value.then;
  7313. } catch (error) {
  7314. reject(promise, error);
  7315. return;
  7316. }
  7317. handleMaybeThenable(promise, value, then$$1);
  7318. } else {
  7319. fulfill(promise, value);
  7320. }
  7321. }
  7322. function publishRejection(promise) {
  7323. if (promise._onerror) {
  7324. promise._onerror(promise._result);
  7325. }
  7326. publish(promise);
  7327. }
  7328. function fulfill(promise, value) {
  7329. if (promise._state !== PENDING) {
  7330. return;
  7331. }
  7332. promise._result = value;
  7333. promise._state = FULFILLED;
  7334. if (promise._subscribers.length !== 0) {
  7335. asap(publish, promise);
  7336. }
  7337. }
  7338. function reject(promise, reason) {
  7339. if (promise._state !== PENDING) {
  7340. return;
  7341. }
  7342. promise._state = REJECTED;
  7343. promise._result = reason;
  7344. asap(publishRejection, promise);
  7345. }
  7346. function subscribe(parent, child, onFulfillment, onRejection) {
  7347. var _subscribers = parent._subscribers;
  7348. var length = _subscribers.length;
  7349. parent._onerror = null;
  7350. _subscribers[length] = child;
  7351. _subscribers[length + FULFILLED] = onFulfillment;
  7352. _subscribers[length + REJECTED] = onRejection;
  7353. if (length === 0 && parent._state) {
  7354. asap(publish, parent);
  7355. }
  7356. }
  7357. function publish(promise) {
  7358. var subscribers = promise._subscribers;
  7359. var settled = promise._state;
  7360. if (subscribers.length === 0) {
  7361. return;
  7362. }
  7363. var child = void 0,
  7364. callback = void 0,
  7365. detail = promise._result;
  7366. for (var i = 0; i < subscribers.length; i += 3) {
  7367. child = subscribers[i];
  7368. callback = subscribers[i + settled];
  7369. if (child) {
  7370. invokeCallback(settled, child, callback, detail);
  7371. } else {
  7372. callback(detail);
  7373. }
  7374. }
  7375. promise._subscribers.length = 0;
  7376. }
  7377. function invokeCallback(settled, promise, callback, detail) {
  7378. var hasCallback = isFunction(callback),
  7379. value = void 0,
  7380. error = void 0,
  7381. succeeded = true;
  7382. if (hasCallback) {
  7383. try {
  7384. value = callback(detail);
  7385. } catch (e) {
  7386. succeeded = false;
  7387. error = e;
  7388. }
  7389. if (promise === value) {
  7390. reject(promise, cannotReturnOwn());
  7391. return;
  7392. }
  7393. } else {
  7394. value = detail;
  7395. }
  7396. if (promise._state !== PENDING) ; else if (hasCallback && succeeded) {
  7397. resolve(promise, value);
  7398. } else if (succeeded === false) {
  7399. reject(promise, error);
  7400. } else if (settled === FULFILLED) {
  7401. fulfill(promise, value);
  7402. } else if (settled === REJECTED) {
  7403. reject(promise, value);
  7404. }
  7405. }
  7406. function initializePromise(promise, resolver) {
  7407. try {
  7408. resolver(function resolvePromise(value) {
  7409. resolve(promise, value);
  7410. }, function rejectPromise(reason) {
  7411. reject(promise, reason);
  7412. });
  7413. } catch (e) {
  7414. reject(promise, e);
  7415. }
  7416. }
  7417. var id = 0;
  7418. function nextId() {
  7419. return id++;
  7420. }
  7421. function makePromise(promise) {
  7422. promise[PROMISE_ID] = id++;
  7423. promise._state = undefined;
  7424. promise._result = undefined;
  7425. promise._subscribers = [];
  7426. }
  7427. function validationError() {
  7428. return new Error('Array Methods must be provided an Array');
  7429. }
  7430. var Enumerator = function () {
  7431. function Enumerator(Constructor, input) {
  7432. this._instanceConstructor = Constructor;
  7433. this.promise = new Constructor(noop);
  7434. if (!this.promise[PROMISE_ID]) {
  7435. makePromise(this.promise);
  7436. }
  7437. if (isArray(input)) {
  7438. this.length = input.length;
  7439. this._remaining = input.length;
  7440. this._result = new Array(this.length);
  7441. if (this.length === 0) {
  7442. fulfill(this.promise, this._result);
  7443. } else {
  7444. this.length = this.length || 0;
  7445. this._enumerate(input);
  7446. if (this._remaining === 0) {
  7447. fulfill(this.promise, this._result);
  7448. }
  7449. }
  7450. } else {
  7451. reject(this.promise, validationError());
  7452. }
  7453. }
  7454. Enumerator.prototype._enumerate = function _enumerate(input) {
  7455. for (var i = 0; this._state === PENDING && i < input.length; i++) {
  7456. this._eachEntry(input[i], i);
  7457. }
  7458. };
  7459. Enumerator.prototype._eachEntry = function _eachEntry(entry, i) {
  7460. var c = this._instanceConstructor;
  7461. var resolve$$1 = c.resolve;
  7462. if (resolve$$1 === resolve$1) {
  7463. var _then = void 0;
  7464. var error = void 0;
  7465. var didError = false;
  7466. try {
  7467. _then = entry.then;
  7468. } catch (e) {
  7469. didError = true;
  7470. error = e;
  7471. }
  7472. if (_then === then && entry._state !== PENDING) {
  7473. this._settledAt(entry._state, i, entry._result);
  7474. } else if (typeof _then !== 'function') {
  7475. this._remaining--;
  7476. this._result[i] = entry;
  7477. } else if (c === Promise$1) {
  7478. var promise = new c(noop);
  7479. if (didError) {
  7480. reject(promise, error);
  7481. } else {
  7482. handleMaybeThenable(promise, entry, _then);
  7483. }
  7484. this._willSettleAt(promise, i);
  7485. } else {
  7486. this._willSettleAt(new c(function (resolve$$1) {
  7487. return resolve$$1(entry);
  7488. }), i);
  7489. }
  7490. } else {
  7491. this._willSettleAt(resolve$$1(entry), i);
  7492. }
  7493. };
  7494. Enumerator.prototype._settledAt = function _settledAt(state, i, value) {
  7495. var promise = this.promise;
  7496. if (promise._state === PENDING) {
  7497. this._remaining--;
  7498. if (state === REJECTED) {
  7499. reject(promise, value);
  7500. } else {
  7501. this._result[i] = value;
  7502. }
  7503. }
  7504. if (this._remaining === 0) {
  7505. fulfill(promise, this._result);
  7506. }
  7507. };
  7508. Enumerator.prototype._willSettleAt = function _willSettleAt(promise, i) {
  7509. var enumerator = this;
  7510. subscribe(promise, undefined, function (value) {
  7511. return enumerator._settledAt(FULFILLED, i, value);
  7512. }, function (reason) {
  7513. return enumerator._settledAt(REJECTED, i, reason);
  7514. });
  7515. };
  7516. return Enumerator;
  7517. }();
  7518. /**
  7519. `Promise.all` accepts an array of promises, and returns a new promise which
  7520. is fulfilled with an array of fulfillment values for the passed promises, or
  7521. rejected with the reason of the first passed promise to be rejected. It casts all
  7522. elements of the passed iterable to promises as it runs this algorithm.
  7523. Example:
  7524. ```javascript
  7525. let promise1 = resolve(1);
  7526. let promise2 = resolve(2);
  7527. let promise3 = resolve(3);
  7528. let promises = [ promise1, promise2, promise3 ];
  7529. Promise.all(promises).then(function(array){
  7530. // The array here would be [ 1, 2, 3 ];
  7531. });
  7532. ```
  7533. If any of the `promises` given to `all` are rejected, the first promise
  7534. that is rejected will be given as an argument to the returned promises's
  7535. rejection handler. For example:
  7536. Example:
  7537. ```javascript
  7538. let promise1 = resolve(1);
  7539. let promise2 = reject(new Error("2"));
  7540. let promise3 = reject(new Error("3"));
  7541. let promises = [ promise1, promise2, promise3 ];
  7542. Promise.all(promises).then(function(array){
  7543. // Code here never runs because there are rejected promises!
  7544. }, function(error) {
  7545. // error.message === "2"
  7546. });
  7547. ```
  7548. @method all
  7549. @static
  7550. @param {Array} entries array of promises
  7551. @param {String} label optional string for labeling the promise.
  7552. Useful for tooling.
  7553. @return {Promise} promise that is fulfilled when all `promises` have been
  7554. fulfilled, or rejected if any of them become rejected.
  7555. @static
  7556. */
  7557. function all(entries) {
  7558. return new Enumerator(this, entries).promise;
  7559. }
  7560. /**
  7561. `Promise.race` returns a new promise which is settled in the same way as the
  7562. first passed promise to settle.
  7563. Example:
  7564. ```javascript
  7565. let promise1 = new Promise(function(resolve, reject){
  7566. setTimeout(function(){
  7567. resolve('promise 1');
  7568. }, 200);
  7569. });
  7570. let promise2 = new Promise(function(resolve, reject){
  7571. setTimeout(function(){
  7572. resolve('promise 2');
  7573. }, 100);
  7574. });
  7575. Promise.race([promise1, promise2]).then(function(result){
  7576. // result === 'promise 2' because it was resolved before promise1
  7577. // was resolved.
  7578. });
  7579. ```
  7580. `Promise.race` is deterministic in that only the state of the first
  7581. settled promise matters. For example, even if other promises given to the
  7582. `promises` array argument are resolved, but the first settled promise has
  7583. become rejected before the other promises became fulfilled, the returned
  7584. promise will become rejected:
  7585. ```javascript
  7586. let promise1 = new Promise(function(resolve, reject){
  7587. setTimeout(function(){
  7588. resolve('promise 1');
  7589. }, 200);
  7590. });
  7591. let promise2 = new Promise(function(resolve, reject){
  7592. setTimeout(function(){
  7593. reject(new Error('promise 2'));
  7594. }, 100);
  7595. });
  7596. Promise.race([promise1, promise2]).then(function(result){
  7597. // Code here never runs
  7598. }, function(reason){
  7599. // reason.message === 'promise 2' because promise 2 became rejected before
  7600. // promise 1 became fulfilled
  7601. });
  7602. ```
  7603. An example real-world use case is implementing timeouts:
  7604. ```javascript
  7605. Promise.race([ajax('foo.json'), timeout(5000)])
  7606. ```
  7607. @method race
  7608. @static
  7609. @param {Array} promises array of promises to observe
  7610. Useful for tooling.
  7611. @return {Promise} a promise which settles in the same way as the first passed
  7612. promise to settle.
  7613. */
  7614. function race(entries) {
  7615. /*jshint validthis:true */
  7616. var Constructor = this;
  7617. if (!isArray(entries)) {
  7618. return new Constructor(function (_, reject) {
  7619. return reject(new TypeError('You must pass an array to race.'));
  7620. });
  7621. } else {
  7622. return new Constructor(function (resolve, reject) {
  7623. var length = entries.length;
  7624. for (var i = 0; i < length; i++) {
  7625. Constructor.resolve(entries[i]).then(resolve, reject);
  7626. }
  7627. });
  7628. }
  7629. }
  7630. /**
  7631. `Promise.reject` returns a promise rejected with the passed `reason`.
  7632. It is shorthand for the following:
  7633. ```javascript
  7634. let promise = new Promise(function(resolve, reject){
  7635. reject(new Error('WHOOPS'));
  7636. });
  7637. promise.then(function(value){
  7638. // Code here doesn't run because the promise is rejected!
  7639. }, function(reason){
  7640. // reason.message === 'WHOOPS'
  7641. });
  7642. ```
  7643. Instead of writing the above, your code now simply becomes the following:
  7644. ```javascript
  7645. let promise = Promise.reject(new Error('WHOOPS'));
  7646. promise.then(function(value){
  7647. // Code here doesn't run because the promise is rejected!
  7648. }, function(reason){
  7649. // reason.message === 'WHOOPS'
  7650. });
  7651. ```
  7652. @method reject
  7653. @static
  7654. @param {Any} reason value that the returned promise will be rejected with.
  7655. Useful for tooling.
  7656. @return {Promise} a promise rejected with the given `reason`.
  7657. */
  7658. function reject$1(reason) {
  7659. /*jshint validthis:true */
  7660. var Constructor = this;
  7661. var promise = new Constructor(noop);
  7662. reject(promise, reason);
  7663. return promise;
  7664. }
  7665. function needsResolver() {
  7666. throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');
  7667. }
  7668. function needsNew() {
  7669. throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");
  7670. }
  7671. /**
  7672. Promise objects represent the eventual result of an asynchronous operation. The
  7673. primary way of interacting with a promise is through its `then` method, which
  7674. registers callbacks to receive either a promise's eventual value or the reason
  7675. why the promise cannot be fulfilled.
  7676. Terminology
  7677. -----------
  7678. - `promise` is an object or function with a `then` method whose behavior conforms to this specification.
  7679. - `thenable` is an object or function that defines a `then` method.
  7680. - `value` is any legal JavaScript value (including undefined, a thenable, or a promise).
  7681. - `exception` is a value that is thrown using the throw statement.
  7682. - `reason` is a value that indicates why a promise was rejected.
  7683. - `settled` the final resting state of a promise, fulfilled or rejected.
  7684. A promise can be in one of three states: pending, fulfilled, or rejected.
  7685. Promises that are fulfilled have a fulfillment value and are in the fulfilled
  7686. state. Promises that are rejected have a rejection reason and are in the
  7687. rejected state. A fulfillment value is never a thenable.
  7688. Promises can also be said to *resolve* a value. If this value is also a
  7689. promise, then the original promise's settled state will match the value's
  7690. settled state. So a promise that *resolves* a promise that rejects will
  7691. itself reject, and a promise that *resolves* a promise that fulfills will
  7692. itself fulfill.
  7693. Basic Usage:
  7694. ------------
  7695. ```js
  7696. let promise = new Promise(function(resolve, reject) {
  7697. // on success
  7698. resolve(value);
  7699. // on failure
  7700. reject(reason);
  7701. });
  7702. promise.then(function(value) {
  7703. // on fulfillment
  7704. }, function(reason) {
  7705. // on rejection
  7706. });
  7707. ```
  7708. Advanced Usage:
  7709. ---------------
  7710. Promises shine when abstracting away asynchronous interactions such as
  7711. `XMLHttpRequest`s.
  7712. ```js
  7713. function getJSON(url) {
  7714. return new Promise(function(resolve, reject){
  7715. let xhr = new XMLHttpRequest();
  7716. xhr.open('GET', url);
  7717. xhr.onreadystatechange = handler;
  7718. xhr.responseType = 'json';
  7719. xhr.setRequestHeader('Accept', 'application/json');
  7720. xhr.send();
  7721. function handler() {
  7722. if (this.readyState === this.DONE) {
  7723. if (this.status === 200) {
  7724. resolve(this.response);
  7725. } else {
  7726. reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']'));
  7727. }
  7728. }
  7729. };
  7730. });
  7731. }
  7732. getJSON('/posts.json').then(function(json) {
  7733. // on fulfillment
  7734. }, function(reason) {
  7735. // on rejection
  7736. });
  7737. ```
  7738. Unlike callbacks, promises are great composable primitives.
  7739. ```js
  7740. Promise.all([
  7741. getJSON('/posts'),
  7742. getJSON('/comments')
  7743. ]).then(function(values){
  7744. values[0] // => postsJSON
  7745. values[1] // => commentsJSON
  7746. return values;
  7747. });
  7748. ```
  7749. @class Promise
  7750. @param {Function} resolver
  7751. Useful for tooling.
  7752. @constructor
  7753. */
  7754. var Promise$1 = function () {
  7755. function Promise(resolver) {
  7756. this[PROMISE_ID] = nextId();
  7757. this._result = this._state = undefined;
  7758. this._subscribers = [];
  7759. if (noop !== resolver) {
  7760. typeof resolver !== 'function' && needsResolver();
  7761. this instanceof Promise ? initializePromise(this, resolver) : needsNew();
  7762. }
  7763. }
  7764. /**
  7765. The primary way of interacting with a promise is through its `then` method,
  7766. which registers callbacks to receive either a promise's eventual value or the
  7767. reason why the promise cannot be fulfilled.
  7768. ```js
  7769. findUser().then(function(user){
  7770. // user is available
  7771. }, function(reason){
  7772. // user is unavailable, and you are given the reason why
  7773. });
  7774. ```
  7775. Chaining
  7776. --------
  7777. The return value of `then` is itself a promise. This second, 'downstream'
  7778. promise is resolved with the return value of the first promise's fulfillment
  7779. or rejection handler, or rejected if the handler throws an exception.
  7780. ```js
  7781. findUser().then(function (user) {
  7782. return user.name;
  7783. }, function (reason) {
  7784. return 'default name';
  7785. }).then(function (userName) {
  7786. // If `findUser` fulfilled, `userName` will be the user's name, otherwise it
  7787. // will be `'default name'`
  7788. });
  7789. findUser().then(function (user) {
  7790. throw new Error('Found user, but still unhappy');
  7791. }, function (reason) {
  7792. throw new Error('`findUser` rejected and we're unhappy');
  7793. }).then(function (value) {
  7794. // never reached
  7795. }, function (reason) {
  7796. // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.
  7797. // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'.
  7798. });
  7799. ```
  7800. If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream.
  7801. ```js
  7802. findUser().then(function (user) {
  7803. throw new PedagogicalException('Upstream error');
  7804. }).then(function (value) {
  7805. // never reached
  7806. }).then(function (value) {
  7807. // never reached
  7808. }, function (reason) {
  7809. // The `PedgagocialException` is propagated all the way down to here
  7810. });
  7811. ```
  7812. Assimilation
  7813. ------------
  7814. Sometimes the value you want to propagate to a downstream promise can only be
  7815. retrieved asynchronously. This can be achieved by returning a promise in the
  7816. fulfillment or rejection handler. The downstream promise will then be pending
  7817. until the returned promise is settled. This is called *assimilation*.
  7818. ```js
  7819. findUser().then(function (user) {
  7820. return findCommentsByAuthor(user);
  7821. }).then(function (comments) {
  7822. // The user's comments are now available
  7823. });
  7824. ```
  7825. If the assimliated promise rejects, then the downstream promise will also reject.
  7826. ```js
  7827. findUser().then(function (user) {
  7828. return findCommentsByAuthor(user);
  7829. }).then(function (comments) {
  7830. // If `findCommentsByAuthor` fulfills, we'll have the value here
  7831. }, function (reason) {
  7832. // If `findCommentsByAuthor` rejects, we'll have the reason here
  7833. });
  7834. ```
  7835. Simple Example
  7836. --------------
  7837. Synchronous Example
  7838. ```javascript
  7839. let result;
  7840. try {
  7841. result = findResult();
  7842. // success
  7843. } catch(reason) {
  7844. // failure
  7845. }
  7846. ```
  7847. Errback Example
  7848. ```js
  7849. findResult(function(result, err){
  7850. if (err) {
  7851. // failure
  7852. } else {
  7853. // success
  7854. }
  7855. });
  7856. ```
  7857. Promise Example;
  7858. ```javascript
  7859. findResult().then(function(result){
  7860. // success
  7861. }, function(reason){
  7862. // failure
  7863. });
  7864. ```
  7865. Advanced Example
  7866. --------------
  7867. Synchronous Example
  7868. ```javascript
  7869. let author, books;
  7870. try {
  7871. author = findAuthor();
  7872. books = findBooksByAuthor(author);
  7873. // success
  7874. } catch(reason) {
  7875. // failure
  7876. }
  7877. ```
  7878. Errback Example
  7879. ```js
  7880. function foundBooks(books) {
  7881. }
  7882. function failure(reason) {
  7883. }
  7884. findAuthor(function(author, err){
  7885. if (err) {
  7886. failure(err);
  7887. // failure
  7888. } else {
  7889. try {
  7890. findBoooksByAuthor(author, function(books, err) {
  7891. if (err) {
  7892. failure(err);
  7893. } else {
  7894. try {
  7895. foundBooks(books);
  7896. } catch(reason) {
  7897. failure(reason);
  7898. }
  7899. }
  7900. });
  7901. } catch(error) {
  7902. failure(err);
  7903. }
  7904. // success
  7905. }
  7906. });
  7907. ```
  7908. Promise Example;
  7909. ```javascript
  7910. findAuthor().
  7911. then(findBooksByAuthor).
  7912. then(function(books){
  7913. // found books
  7914. }).catch(function(reason){
  7915. // something went wrong
  7916. });
  7917. ```
  7918. @method then
  7919. @param {Function} onFulfilled
  7920. @param {Function} onRejected
  7921. Useful for tooling.
  7922. @return {Promise}
  7923. */
  7924. /**
  7925. `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same
  7926. as the catch block of a try/catch statement.
  7927. ```js
  7928. function findAuthor(){
  7929. throw new Error('couldn't find that author');
  7930. }
  7931. // synchronous
  7932. try {
  7933. findAuthor();
  7934. } catch(reason) {
  7935. // something went wrong
  7936. }
  7937. // async with promises
  7938. findAuthor().catch(function(reason){
  7939. // something went wrong
  7940. });
  7941. ```
  7942. @method catch
  7943. @param {Function} onRejection
  7944. Useful for tooling.
  7945. @return {Promise}
  7946. */
  7947. Promise.prototype.catch = function _catch(onRejection) {
  7948. return this.then(null, onRejection);
  7949. };
  7950. /**
  7951. `finally` will be invoked regardless of the promise's fate just as native
  7952. try/catch/finally behaves
  7953. Synchronous example:
  7954. ```js
  7955. findAuthor() {
  7956. if (Math.random() > 0.5) {
  7957. throw new Error();
  7958. }
  7959. return new Author();
  7960. }
  7961. try {
  7962. return findAuthor(); // succeed or fail
  7963. } catch(error) {
  7964. return findOtherAuther();
  7965. } finally {
  7966. // always runs
  7967. // doesn't affect the return value
  7968. }
  7969. ```
  7970. Asynchronous example:
  7971. ```js
  7972. findAuthor().catch(function(reason){
  7973. return findOtherAuther();
  7974. }).finally(function(){
  7975. // author was either found, or not
  7976. });
  7977. ```
  7978. @method finally
  7979. @param {Function} callback
  7980. @return {Promise}
  7981. */
  7982. Promise.prototype.finally = function _finally(callback) {
  7983. var promise = this;
  7984. var constructor = promise.constructor;
  7985. if (isFunction(callback)) {
  7986. return promise.then(function (value) {
  7987. return constructor.resolve(callback()).then(function () {
  7988. return value;
  7989. });
  7990. }, function (reason) {
  7991. return constructor.resolve(callback()).then(function () {
  7992. throw reason;
  7993. });
  7994. });
  7995. }
  7996. return promise.then(callback, callback);
  7997. };
  7998. return Promise;
  7999. }();
  8000. Promise$1.prototype.then = then;
  8001. Promise$1.all = all;
  8002. Promise$1.race = race;
  8003. Promise$1.resolve = resolve$1;
  8004. Promise$1.reject = reject$1;
  8005. Promise$1._setScheduler = setScheduler;
  8006. Promise$1._setAsap = setAsap;
  8007. Promise$1._asap = asap;
  8008. /*global self*/
  8009. function polyfill() {
  8010. var local = void 0;
  8011. if (typeof commonjsGlobal !== 'undefined') {
  8012. local = commonjsGlobal;
  8013. } else if (typeof self !== 'undefined') {
  8014. local = self;
  8015. } else {
  8016. try {
  8017. local = Function('return this')();
  8018. } catch (e) {
  8019. throw new Error('polyfill failed because global object is unavailable in this environment');
  8020. }
  8021. }
  8022. var P = local.Promise;
  8023. if (P) {
  8024. var promiseToString = null;
  8025. try {
  8026. promiseToString = Object.prototype.toString.call(P.resolve());
  8027. } catch (e) {
  8028. // silently ignored
  8029. }
  8030. if (promiseToString === '[object Promise]' && !P.cast) {
  8031. return;
  8032. }
  8033. }
  8034. local.Promise = Promise$1;
  8035. }
  8036. // Strange compat..
  8037. Promise$1.polyfill = polyfill;
  8038. Promise$1.Promise = Promise$1;
  8039. return Promise$1;
  8040. })));
  8041. });
  8042. class RTCEndpoint extends Event$1 {
  8043. constructor(options) {
  8044. super('RTCPusherPlayer');
  8045. this.TAG = '[RTCPusherPlayer]';
  8046. let defaults = {
  8047. element: '',
  8048. // html video element
  8049. debug: false,
  8050. // if output debug log
  8051. zlmsdpUrl: '',
  8052. simulcast: false,
  8053. useCamera: true,
  8054. audioEnable: true,
  8055. videoEnable: true,
  8056. recvOnly: false,
  8057. resolution: {
  8058. w: 0,
  8059. h: 0
  8060. },
  8061. usedatachannel: false,
  8062. videoId: '',
  8063. audioId: ''
  8064. };
  8065. this.options = Object.assign({}, defaults, options);
  8066. if (this.options.debug) {
  8067. setLogger();
  8068. }
  8069. this.e = {
  8070. onicecandidate: this._onIceCandidate.bind(this),
  8071. ontrack: this._onTrack.bind(this),
  8072. onicecandidateerror: this._onIceCandidateError.bind(this),
  8073. onconnectionstatechange: this._onconnectionstatechange.bind(this),
  8074. ondatachannelopen: this._onDataChannelOpen.bind(this),
  8075. ondatachannelmsg: this._onDataChannelMsg.bind(this),
  8076. ondatachannelerr: this._onDataChannelErr.bind(this),
  8077. ondatachannelclose: this._onDataChannelClose.bind(this)
  8078. };
  8079. this._remoteStream = null;
  8080. this._localStream = null;
  8081. this._tracks = [];
  8082. this.pc = new RTCPeerConnection(null);
  8083. this.pc.onicecandidate = this.e.onicecandidate;
  8084. this.pc.onicecandidateerror = this.e.onicecandidateerror;
  8085. this.pc.ontrack = this.e.ontrack;
  8086. this.pc.onconnectionstatechange = this.e.onconnectionstatechange;
  8087. this.datachannel = null;
  8088. if (this.options.usedatachannel) {
  8089. this.datachannel = this.pc.createDataChannel('chat');
  8090. this.datachannel.onclose = this.e.ondatachannelclose;
  8091. this.datachannel.onerror = this.e.ondatachannelerr;
  8092. this.datachannel.onmessage = this.e.ondatachannelmsg;
  8093. this.datachannel.onopen = this.e.ondatachannelopen;
  8094. }
  8095. if (!this.options.recvOnly && (this.options.audioEnable || this.options.videoEnable)) this.start();else this.receive();
  8096. }
  8097. receive() {
  8098. //debug.error(this.TAG,'this not implement');
  8099. const AudioTransceiverInit = {
  8100. direction: 'recvonly',
  8101. sendEncodings: []
  8102. };
  8103. const VideoTransceiverInit = {
  8104. direction: 'recvonly',
  8105. sendEncodings: []
  8106. };
  8107. if (this.options.videoEnable) {
  8108. this.pc.addTransceiver('video', VideoTransceiverInit);
  8109. }
  8110. if (this.options.audioEnable) {
  8111. this.pc.addTransceiver('audio', AudioTransceiverInit);
  8112. }
  8113. this.pc.createOffer().then(desc => {
  8114. log(this.TAG, 'offer:', desc.sdp);
  8115. this.pc.setLocalDescription(desc).then(() => {
  8116. axios({
  8117. method: 'post',
  8118. url: this.options.zlmsdpUrl,
  8119. responseType: 'json',
  8120. data: desc.sdp,
  8121. headers: {
  8122. 'Content-Type': 'text/plain;charset=utf-8'
  8123. }
  8124. }).then(response => {
  8125. let ret = response.data; //JSON.parse(response.data);
  8126. if (ret.code != 0) {
  8127. // mean failed for offer/anwser exchange
  8128. this.dispatch(Events$1.WEBRTC_OFFER_ANWSER_EXCHANGE_FAILED, ret);
  8129. return;
  8130. }
  8131. let anwser = {};
  8132. anwser.sdp = ret.sdp;
  8133. anwser.type = 'answer';
  8134. log(this.TAG, 'answer:', ret.sdp);
  8135. this.pc.setRemoteDescription(anwser).then(() => {
  8136. log(this.TAG, 'set remote sucess');
  8137. }).catch(e => {
  8138. error(this.TAG, e);
  8139. });
  8140. });
  8141. });
  8142. }).catch(e => {
  8143. error(this.TAG, e);
  8144. });
  8145. }
  8146. start() {
  8147. let videoConstraints = false;
  8148. let audioConstraints = false;
  8149. if (this.options.useCamera) {
  8150. if (this.options.videoEnable) videoConstraints = new VideoTrackConstraints(VideoSourceInfo.CAMERA);
  8151. if (this.options.audioEnable) audioConstraints = new AudioTrackConstraints(AudioSourceInfo.MIC);
  8152. } else {
  8153. if (this.options.videoEnable) {
  8154. videoConstraints = new VideoTrackConstraints(VideoSourceInfo.SCREENCAST);
  8155. if (this.options.audioEnable) audioConstraints = new AudioTrackConstraints(AudioSourceInfo.SCREENCAST);
  8156. } else {
  8157. if (this.options.audioEnable) audioConstraints = new AudioTrackConstraints(AudioSourceInfo.MIC);else {
  8158. // error shared display media not only audio
  8159. error(this.TAG, 'error paramter');
  8160. }
  8161. }
  8162. }
  8163. if (this.options.resolution.w != 0 && this.options.resolution.h != 0 && typeof videoConstraints == 'object') {
  8164. videoConstraints.resolution = new Resolution(this.options.resolution.w, this.options.resolution.h);
  8165. }
  8166. if (typeof videoConstraints == 'object' && this.options.videoId != '') {
  8167. videoConstraints.deviceId = this.options.videoId;
  8168. }
  8169. if (typeof audioConstraints == 'object' && this.options.audioId != '') {
  8170. audioConstraints.deviceId = this.options.audioId;
  8171. }
  8172. MediaStreamFactory.createMediaStream(new StreamConstraints(audioConstraints, videoConstraints)).then(stream => {
  8173. this._localStream = stream;
  8174. this.dispatch(Events$1.WEBRTC_ON_LOCAL_STREAM, stream);
  8175. const AudioTransceiverInit = {
  8176. direction: 'sendrecv',
  8177. sendEncodings: []
  8178. };
  8179. const VideoTransceiverInit = {
  8180. direction: 'sendrecv',
  8181. sendEncodings: []
  8182. };
  8183. if (this.options.simulcast && stream.getVideoTracks().length > 0) {
  8184. VideoTransceiverInit.sendEncodings = [{
  8185. rid: 'h',
  8186. active: true,
  8187. maxBitrate: 1000000
  8188. }, {
  8189. rid: 'm',
  8190. active: true,
  8191. maxBitrate: 500000,
  8192. scaleResolutionDownBy: 2
  8193. }, {
  8194. rid: 'l',
  8195. active: true,
  8196. maxBitrate: 200000,
  8197. scaleResolutionDownBy: 4
  8198. }];
  8199. }
  8200. if (this.options.audioEnable) {
  8201. if (stream.getAudioTracks().length > 0) {
  8202. this.pc.addTransceiver(stream.getAudioTracks()[0], AudioTransceiverInit);
  8203. } else {
  8204. AudioTransceiverInit.direction = 'recvonly';
  8205. this.pc.addTransceiver('audio', AudioTransceiverInit);
  8206. }
  8207. }
  8208. if (this.options.videoEnable) {
  8209. if (stream.getVideoTracks().length > 0) {
  8210. this.pc.addTransceiver(stream.getVideoTracks()[0], VideoTransceiverInit);
  8211. } else {
  8212. VideoTransceiverInit.direction = 'recvonly';
  8213. this.pc.addTransceiver('video', VideoTransceiverInit);
  8214. }
  8215. }
  8216. /*
  8217. stream.getTracks().forEach((track,idx)=>{
  8218. debug.log(this.TAG,track);
  8219. this.pc.addTrack(track);
  8220. });
  8221. */
  8222. this.pc.createOffer().then(desc => {
  8223. log(this.TAG, 'offer:', desc.sdp);
  8224. this.pc.setLocalDescription(desc).then(() => {
  8225. axios({
  8226. method: 'post',
  8227. url: this.options.zlmsdpUrl,
  8228. responseType: 'json',
  8229. data: desc.sdp,
  8230. headers: {
  8231. 'Content-Type': 'text/plain;charset=utf-8'
  8232. }
  8233. }).then(response => {
  8234. let ret = response.data; //JSON.parse(response.data);
  8235. if (ret.code != 0) {
  8236. // mean failed for offer/anwser exchange
  8237. this.dispatch(Events$1.WEBRTC_OFFER_ANWSER_EXCHANGE_FAILED, ret);
  8238. return;
  8239. }
  8240. let anwser = {};
  8241. anwser.sdp = ret.sdp;
  8242. anwser.type = 'answer';
  8243. log(this.TAG, 'answer:', ret.sdp);
  8244. this.pc.setRemoteDescription(anwser).then(() => {
  8245. log(this.TAG, 'set remote sucess');
  8246. }).catch(e => {
  8247. error(this.TAG, e);
  8248. });
  8249. });
  8250. });
  8251. }).catch(e => {
  8252. error(this.TAG, e);
  8253. });
  8254. }).catch(e => {
  8255. this.dispatch(Events$1.CAPTURE_STREAM_FAILED);
  8256. //debug.error(this.TAG,e);
  8257. });
  8258. //const offerOptions = {};
  8259. /*
  8260. if (typeof this.pc.addTransceiver === 'function') {
  8261. // |direction| seems not working on Safari.
  8262. this.pc.addTransceiver('audio', { direction: 'recvonly' });
  8263. this.pc.addTransceiver('video', { direction: 'recvonly' });
  8264. } else {
  8265. offerOptions.offerToReceiveAudio = true;
  8266. offerOptions.offerToReceiveVideo = true;
  8267. }
  8268. */
  8269. }
  8270. _onIceCandidate(event) {
  8271. if (event.candidate) {
  8272. log(this.TAG, 'Remote ICE candidate: \n ' + event.candidate.candidate);
  8273. // Send the candidate to the remote peer
  8274. }
  8275. }
  8276. _onTrack(event) {
  8277. this._tracks.push(event.track);
  8278. if (this.options.element && event.streams && event.streams.length > 0) {
  8279. this.options.element.srcObject = event.streams[0];
  8280. this._remoteStream = event.streams[0];
  8281. this.dispatch(Events$1.WEBRTC_ON_REMOTE_STREAMS, event);
  8282. } else {
  8283. if (this.pc.getReceivers().length == this._tracks.length) {
  8284. log(this.TAG, 'play remote stream ');
  8285. this._remoteStream = new MediaStream(this._tracks);
  8286. this.options.element.srcObject = this._remoteStream;
  8287. } else {
  8288. error(this.TAG, 'wait stream track finish');
  8289. }
  8290. }
  8291. }
  8292. _onIceCandidateError(event) {
  8293. this.dispatch(Events$1.WEBRTC_ICE_CANDIDATE_ERROR, event);
  8294. }
  8295. _onconnectionstatechange(event) {
  8296. this.dispatch(Events$1.WEBRTC_ON_CONNECTION_STATE_CHANGE, this.pc.connectionState);
  8297. }
  8298. _onDataChannelOpen(event) {
  8299. log(this.TAG, 'ondatachannel open:', event);
  8300. this.dispatch(Events$1.WEBRTC_ON_DATA_CHANNEL_OPEN, event);
  8301. }
  8302. _onDataChannelMsg(event) {
  8303. log(this.TAG, 'ondatachannel msg:', event);
  8304. this.dispatch(Events$1.WEBRTC_ON_DATA_CHANNEL_MSG, event);
  8305. }
  8306. _onDataChannelErr(event) {
  8307. log(this.TAG, 'ondatachannel err:', event);
  8308. this.dispatch(Events$1.WEBRTC_ON_DATA_CHANNEL_ERR, event);
  8309. }
  8310. _onDataChannelClose(event) {
  8311. log(this.TAG, 'ondatachannel close:', event);
  8312. this.dispatch(Events$1.WEBRTC_ON_DATA_CHANNEL_CLOSE, event);
  8313. }
  8314. sendMsg(data) {
  8315. if (this.datachannel != null) {
  8316. this.datachannel.send(data);
  8317. } else {
  8318. error(this.TAG, 'data channel is null');
  8319. }
  8320. }
  8321. switchVideo(useCamera, deviceId) {
  8322. let videoConstraints = false;
  8323. if (useCamera) {
  8324. videoConstraints = new VideoTrackConstraints(VideoSourceInfo.CAMERA);
  8325. videoConstraints.deviceId = deviceId;
  8326. } else {
  8327. videoConstraints = new VideoTrackConstraints(VideoSourceInfo.SCREENCAST);
  8328. }
  8329. return MediaStreamFactory.createMediaStream(new StreamConstraints(false, videoConstraints)).then(stream => {
  8330. const videosender = this.pc.getSenders().find(e => e.track.kind === 'video');
  8331. if (videosender != null && stream.getVideoTracks().length > 0) {
  8332. this._localStream.removeTrack(videosender.track);
  8333. this._localStream.addTrack(stream.getVideoTracks()[0]);
  8334. // stream change
  8335. this.dispatch(Events$1.WEBRTC_ON_LOCAL_STREAM, this._localStream);
  8336. return videosender.replaceTrack(stream.getVideoTracks()[0]);
  8337. }
  8338. return es6Promise.Promise.reject('video not exist or deviceid not vaild');
  8339. });
  8340. }
  8341. switcAudio(useMic, deviceId) {
  8342. let audioConstraints = false;
  8343. if (useMic) {
  8344. audioConstraints = new AudioTrackConstraints(AudioSourceInfo.MIC);
  8345. audioConstraints.deviceId = deviceId;
  8346. } else {
  8347. audioConstraints = new AudioTrackConstraints(AudioSourceInfo.SCREENCAST);
  8348. }
  8349. return MediaStreamFactory.createMediaStream(new StreamConstraints(audioConstraints, false)).then(stream => {
  8350. const audiosender = this.pc.getSenders().find(e => e.track.kind === 'audio');
  8351. if (audiosender != null && stream.getAudioTracks().length > 0) {
  8352. this._localStream.removeTrack(audiosender.track);
  8353. this._localStream.addTrack(stream.getAudioTracks()[0]);
  8354. // stream change
  8355. this.dispatch(Events$1.WEBRTC_ON_LOCAL_STREAM, this._localStream);
  8356. return audiosender.replaceTrack(stream.getAudioTracks()[0]);
  8357. }
  8358. return es6Promise.Promise.reject('audio not exist or deviceid not vaild');
  8359. });
  8360. }
  8361. closeDataChannel() {
  8362. if (this.datachannel) {
  8363. this.datachannel.close();
  8364. this.datachannel = null;
  8365. }
  8366. }
  8367. close() {
  8368. this.closeDataChannel();
  8369. if (this.pc) {
  8370. this.pc.close();
  8371. this.pc = null;
  8372. }
  8373. if (this.options) {
  8374. this.options = null;
  8375. }
  8376. if (this._localStream) {
  8377. this._localStream.getTracks().forEach((track, idx) => {
  8378. track.stop();
  8379. });
  8380. }
  8381. if (this._remoteStream) {
  8382. this._remoteStream.getTracks().forEach((track, idx) => {
  8383. track.stop();
  8384. });
  8385. }
  8386. this._tracks.forEach((track, idx) => {
  8387. track.stop();
  8388. });
  8389. this._tracks = [];
  8390. }
  8391. get remoteStream() {
  8392. return this._remoteStream;
  8393. }
  8394. get localStream() {
  8395. return this._localStream;
  8396. }
  8397. }
  8398. const quickScan = [{
  8399. 'label': '4K(UHD)',
  8400. 'width': 3840,
  8401. 'height': 2160
  8402. }, {
  8403. 'label': '1080p(FHD)',
  8404. 'width': 1920,
  8405. 'height': 1080
  8406. }, {
  8407. 'label': 'UXGA',
  8408. 'width': 1600,
  8409. 'height': 1200,
  8410. 'ratio': '4:3'
  8411. }, {
  8412. 'label': '720p(HD)',
  8413. 'width': 1280,
  8414. 'height': 720
  8415. }, {
  8416. 'label': 'SVGA',
  8417. 'width': 800,
  8418. 'height': 600
  8419. }, {
  8420. 'label': 'VGA',
  8421. 'width': 640,
  8422. 'height': 480
  8423. }, {
  8424. 'label': '360p(nHD)',
  8425. 'width': 640,
  8426. 'height': 360
  8427. }, {
  8428. 'label': 'CIF',
  8429. 'width': 352,
  8430. 'height': 288
  8431. }, {
  8432. 'label': 'QVGA',
  8433. 'width': 320,
  8434. 'height': 240
  8435. }, {
  8436. 'label': 'QCIF',
  8437. 'width': 176,
  8438. 'height': 144
  8439. }, {
  8440. 'label': 'QQVGA',
  8441. 'width': 160,
  8442. 'height': 120
  8443. }];
  8444. function GetSupportCameraResolutions$1() {
  8445. return new Promise(function (resolve, reject) {
  8446. let resolutions = [];
  8447. let ok = 0;
  8448. let err = 0;
  8449. for (let i = 0; i < quickScan.length; ++i) {
  8450. let videoConstraints = new VideoTrackConstraints(VideoSourceInfo.CAMERA);
  8451. videoConstraints.resolution = new Resolution(quickScan[i].width, quickScan[i].height);
  8452. MediaStreamFactory.createMediaStream(new StreamConstraints(false, videoConstraints)).then(stream => {
  8453. stream.getVideoTracks().forEach(track => track.stop());
  8454. resolutions.push(quickScan[i]);
  8455. ok++;
  8456. if (ok + err == quickScan.length) {
  8457. resolve(resolutions);
  8458. }
  8459. }).catch(e => {
  8460. err++;
  8461. if (ok + err == quickScan.length) {
  8462. resolve(resolutions);
  8463. }
  8464. });
  8465. }
  8466. });
  8467. }
  8468. function GetAllScanResolution$1() {
  8469. return quickScan;
  8470. }
  8471. function isSupportResolution$1(w, h) {
  8472. return new Promise(function (resolve, reject) {
  8473. let videoConstraints = new VideoTrackConstraints(VideoSourceInfo.CAMERA);
  8474. videoConstraints.resolution = new Resolution(w, h);
  8475. MediaStreamFactory.createMediaStream(new StreamConstraints(false, videoConstraints)).then(stream => {
  8476. stream.getVideoTracks().forEach(track => track.stop());
  8477. resolve();
  8478. }).catch(e => {
  8479. reject(e);
  8480. });
  8481. });
  8482. }
  8483. function GetAllMediaDevice$1() {
  8484. return new Promise(function (resolve, reject) {
  8485. if (typeof navigator.mediaDevices != 'object' || typeof navigator.mediaDevices.enumerateDevices != 'function') {
  8486. reject('enumerateDevices() not supported.');
  8487. } else {
  8488. // List cameras and microphones.
  8489. navigator.mediaDevices.enumerateDevices().then(devices => {
  8490. resolve(devices);
  8491. }).catch(err => {
  8492. reject(`${err.name}: ${err.message}`);
  8493. });
  8494. }
  8495. });
  8496. }
  8497. console.log('build date:', BUILD_DATE);
  8498. console.log('version:', VERSION$1);
  8499. const Events = Events$1;
  8500. const Media = media;
  8501. const Endpoint = RTCEndpoint;
  8502. const GetSupportCameraResolutions = GetSupportCameraResolutions$1;
  8503. const GetAllScanResolution = GetAllScanResolution$1;
  8504. const isSupportResolution = isSupportResolution$1;
  8505. const GetAllMediaDevice = GetAllMediaDevice$1;
  8506. exports.Endpoint = Endpoint;
  8507. exports.Events = Events;
  8508. exports.GetAllMediaDevice = GetAllMediaDevice;
  8509. exports.GetAllScanResolution = GetAllScanResolution;
  8510. exports.GetSupportCameraResolutions = GetSupportCameraResolutions;
  8511. exports.Media = Media;
  8512. exports.isSupportResolution = isSupportResolution;
  8513. Object.defineProperty(exports, '__esModule', { value: true });
  8514. return exports;
  8515. })({});
  8516. //# sourceMappingURL=ZLMRTCClient.js.map