N|a;R32Y?dZ7|YD3 Q .!!""###4$$%l%%m&*''@()W))) r* * L++,,?-%-&.,j.-XU.4X/t0''_''3'''\'''p''&'{'','''2'X'n'X''''(( ( (O ( ((B(((L (!(H"(#(2%(a?'(eA((A,(_B/((E0(F1(F2(G3(G?(2HB(JC(PD(YH(cI(hJ(nK(~tL(.zM(N(_O(܊P(kQ(R(;S(HT(U(V(W(X(Y(Z([(X\(](^('_(`(a(b()'c(q(d(n,e(Tf(Tg(DUh(Ui(Vj(]Vk(Vl(Vm(?Wn(Wo(Wp(-Xq(Xr(Ys(MYt(Yu(Yv(1Zw(Zx(Zy( [z([{([|(@\}(\~(\($](t](](^(e^(^(^(;_(_(_(`(Y`(`(`(a(c(d(Ne(f(g(h(k(Bn(5o(o(Ip(u(w((((((((α((`(1((ѵ(˶(((<(4(((( ((b(w( ( (L(((u(>((!(Y$)%)U()))*)-,)e-)11)4)7 )8 )9 ): )> )DA)qC){G)`K)M)P)S)U)W)Z)[)e)q)~)))) ))!)4")5#)6$)7%)8&)9')]:().;))<*)<+)V>,)?-)J.),V/)a0)l1)w2)3)֍4)5)L6)}7)a9)c:)՟;)<)|=)B>)?)(@)'A)B)OC)D)E)F)ìG)H)I)J)K)0L)M)hN)O)P)FQ)R)S)T)U) V)~W)X)Y)Z)5[)\)])<^)_)=`)a)b)-c)V1r 1|11'1217E1 O1F1111$1}'1s+1.171;1Z1aj1z1ځ1}11x1Ɲ11}11ײ11511O151111)11R"2)2+2)<232o 2x/ 2f 2y 2 2+ 2 2 2H (2i )2Nj z?h j?hj@hkAh`lBhmFhCoGhoHhpIhqJhsKh;tLhtMhuNh#vOhvPh wQh|wRh1xShxThyUhzVhC{Wh{Xh|Yh}ZhD~[h~\h/]h%_hbh+jj_jj j[jjjj͎jj؏jjߐjdjjtjj j!jh"j#j$jj%j8&j&'j(j)j*jS+j,j-j~.jI/j,0jD1jˡ2j3jɣ4j 5j)6j7jܧ8j9j6:j;jj?jެ@jEAjBjCjqEjʮFjGjRHjIjJj.KjyLjNjOj}PjQjuRjDzSjTjhUjڳVjOWjXj Yj_Zj[j\jx]jֶ^j,`jajbj@cjdj ejfj,gjljmjDnjrjsjtj,ujývjwjyxjѾyj\zj{jq|j}j'~jjjsjjAjj+jjjj3jj'jjjjj$jcjjpjpj j)jnjjjojjjjjj"jjjj j9 jj{jjfjjjj|jjvj]j5jj j("ju"j"j{#j#j $jS$j$j%%j%jc&j&h'>((((((((((((((((((((v(((((((((((((((((((()D8)(gggggghhhh h hhhhhhhh!h:h;hIENDB`PNG  IHDR:=,IDATcπ |B;p:RL?˟~Fq# n>MIENDB`PNG  IHDRVIDATx^e r'vqb*܋`B Q/iA1ς& W$ E17f-A/X;\o$IENDB`PNG  IHDRIDATxc P6SNIENDB`PNG  IHDRZIDATx^]A 1IJ#=~B_=t"l,x !̤OGAH7iA@"@ EzO[ {ek"t ?nj;TcyIENDB`PNG  IHDR:=3IDATco9{—(V>L٢9u{.tiIENDB`PNG  IHDRѝIDATxc?!?|^:IENDB`PNG  IHDR:=5IDATc=s#Q}b20ıE}3ɰoe ݍA5IENDB`PNG  IHDR:=3IDATc``_) 㙴SC-!w8[#R f j j:C lIENDB`PNG  IHDRѝIDATxc/P`^[rIENDB`PNG  IHDR:=3IDATc/_ L~Ϥ0012ĩb`PBsP uIENDB`PNG  IHDR7IDATxc/hp' # d2dD!CBQ&BjP܀! ; OtmIENDB`PNG  IHDRIDATxc`Pgb``b`a gTrIENDB`PNG  IHDR5IDATcbPB=2L d3 X 2PAZ&n`}8G1IENDB`PNG  IHDR:=3IDATc`ɠCp`d``5 .J,IENDB`PNG  IHDRѝIDATxc`g`0f`d~~IENDB`PNG  IHDR:=3IDATc`B N f Q?q?̿"8ιy7\Lp 3,blsIENDB`PNG  IHDR  6IDATcXB00 7_$4$G#d-}t Ƿ:IENDB`PNG  IHDR  WIDATx^0Г P$IX< A_j @4tCR vA U=}w%'9'7IENDB`PNG  IHDRW{IDATxca_O (e$-jIENDB`PNG  IHDRW{ IDATxcA@w*IENDB`PNG  IHDRW{IDATxc9^0V$t#IENDB`PNG  IHDRJ'VIDATcOpGGnc VA)͚R?eП0f? 60, F0 vIENDB`PNG  IHDRJ'"IDATcsbA$/'//e&Q IENDB`PNG  IHDRJ'WIDATcss*8>|"% 'ueZry S1\ppļS2N^? f``YL$#5IENDB`PNG  IHDR  LIDATxcΟ<0`bogp?9śH8`VEadbs٘&N0R-IENDB`PNG  IHDR  1IDATxcXnE1.9pq#+ĄacFp"q#!IENDB`PNG  IHDR  RIDATxeɱ @ CQOp г R].ȱ,Qt÷_dt'tE7HO8AntZ c!S̅9PmIENDB`PNG  IHDRW{IDATxc6'EIENDB`PNG  IHDRW{ IDATxc$qt}[IENDB`PNG  IHDRW{IDATxch_5"IENDB`PNG  IHDRJ'VIDATcg|pG{&a.VN&M\e$x2?6]0Co׹ A9/*jIENDB`PNG  IHDRJ'!IDATc,,H6d)G _rʄIENDB`PNG  IHDRJ'XIDATxc5;jIaX4@iz{6f.;d↩:9hb^)YXud 300_, @3&Y)IENDB`PNG  IHDR  PIDATmǫ@@sgZ*;Məb]bCg 1O*aά۴3I:iICf ^t3IENDB`PNG  IHDR  7IDATc!sf7$ΑH8{#qb8H$L>rIENDB`PNG  IHDR  VIDATx]ɱ 0 DQ"$hX j,%m ~thޓw3EFȷ?{qk3%"wb٢"!SbfR; 8IENDB`PNG  IHDRW{IDATcazii(@#IENDB`PNG  IHDRW{ IDATxcNC@sgSDIENDB`PNG  IHDRW{IDATxcNNK_2aA@eAb>IENDB`PNG  IHDRJ'VIDATci>f``b寡?+/ sfݯL~cП0{'3;#a L߮s9@. 7#, nIENDB`PNG  IHDRJ'"IDATcb^$7+'Q_|ʒ6IENDB`PNG  IHDRJ'WIDATcʲ<}5 yUgue/olݷp↩,9pR^)YXud 300_,@&`#Q$IENDB`PNG  IHDR ';68IDATx^u0ߐR9)o d:K7QrOQ xD.]ffIENDB`PNG  IHDR Vu\IDATxc?C++@]Ė;? 1|.__"Q"tf̜}!B Aᣋ! 11Hd9Mi@hڰqfFWI9%x^ܞ$IENDB`PNG  IHDR2'7IDATx^ͱ 0F#HvE a ibɍst· ~ w) 9BELAܢTw{rֹu99V\ٹ%OIENDB`PNG  IHDR2'7 IDATc`|!CVQa"X.6/IENDB`PNG  IHDR2'7IDATx^!A e/pHpOOE|Bi!g+kdML;jf41Izqq:l8Wu-th@m|cVM. G;'K,xsJsZ /2-)IENDB`PNG  IHDRdIDATc ߶2X0 @EIENDB`PNG  IHDRdIDATcj uYIENDB`PNG  IHDRdIDATcg!n B<)IENDB`PNG  IHDRF3@JIDATxcM1߶0|` A"mdIy}k͜13D3e@@ @ (1kRc=AIENDB`PNG  IHDRF3@IDATxc\-IENDB`PNG  IHDRF3@LIDATc0| A?Fg31yD*'+12MS}IENDB`PNG  IHDR =Z/IDATxc`d_1h1\-?irU6r8:WIENDB`PNG  IHDR72IDATxc DG X )}ՀWA02 DWFLHd<lCS9IENDB`PNG  IHDRapIDATx^С @D@Q C 3Åd9.pb͊g&/<55`l&Z[ש-gج$(X@Àn vOD sЍ'}m:IENDB`PNG  IHDRa>IDATxcxs?18 |2A R7 58oOx&f8=H a@- 1IENDB`PNG  IHDRaLIDATxcxs?18 |2A R7 p$I>]ߞM  @{!€Z}Li2IENDB`PNG  IHDR!}4IDATxc`b0fd  @ s=lIENDB`PNG  IHDR!}4IDATxc`d0f`e``2 A0#{s IENDB`PNG  IHDR4s&IDATxo!{a^iڬ @/ P C-A.r$"Ga!ے%QDJ%$-RIKx<mI/W@7qq"tZv`@e*~Hgk/>C>uynxq#ϫG8/<]=|!BvCÎst<ُsJps^ _v߿s;~}}:ͽV<9N̹1Mn޼955%IgggAD"fƧnܸ޺u+JY5==v:I64dkmn!GnW5ӬQR MQߥ; fyy8hilnni۶(A)Z^^y~qq!4??F Ø3W^]ZZm}ڵI&#"&nFV+3ϯ{Xdq_w\L_1ӟlԙIÿ H1`k,Tԁ_Xq",c9|ZGgiR9*'{`P,%,||F=Z2G$trV.xLY9ąNw!w DyU/RFLwZef͵nLo0| PEizZJ{v._z ImT Z?uddV*4.-lg8#'I9c7$I|y|Xq{};p0#q'_(DAK?WO8|81c*9.s퇏'@@q N N 88'c>P > N뫖~gZ0ޙ=5U>ˌS65a;ud:t"DE" Ȃr]D@qA%,IwiiqVSsI硃en͉Xx>5Rd(L{CeNxhԹ Pί圧5;woN@Q_nTЯĄREFn{dogr6Xxӝ[\W,UEwY>2Lv~L9]&azv Ƕh[X"(->l4w&:8^h~yļʶ oܧ̓/ny8E#'g =?k{ݾﶛ ckh4WZb%ykd2ZW70I3.{IbU^xi*QH]8E7n=8(Si%´'#rRDWc\ߪy=Ddž7dZJ..`a:8Y\\]ko$%h[ʒv}ǥBGу/ڦ߸\(ͥ5!CLUo֧rꯥ(k<:i" cw -EO)Gup.%;{_y@Pb￙Xq2ʪVFi7-SыlAiG,T3ѕgN ̕w~N Q -@9`}^Z|`^Gf6!gl^PN[hby {\f>Aq=[gRB Oؙ>]T{B89'7WhplIi2:%QwĔ399 Sс*#ynx׌iʈ?u3AڔRҽj7XZ. q ٞ7t DsZWiJ+,uV~q몹$1~ gM˳ Ar xSߞ1:p/,KNN,) X\/xa eDҞwˇrfqrB.1 q !y )͞g"%}~O'yi:G-Ǣ;n}b*f27G|~q^;4\h!W$sQ^/k9hE.-  RL7MhB+F՚owϺҒ2¬,T*?8a(aRNy };7W xXϳ]KHfoO*+3!HlQ&rBڍ$N9!G$)d^ s"y]_ $Xu͌rn1\>p&pPwF rB PN@ @oPNv:BH  BABxfő"ހJD6欬e8..I0/pPu|_[(:J*TKHDJn NM9uCbwBrsS?tmSYt߱2KsBk_VUp ^I?< Au/Sq_LFtHMt,~y\ F/OG<Σ1̬n[MXm'w î҄I"30\3zAXߐum$DÏ%7)fD~+v6s|U)u"I7h rx4]Kfa&oYVnl?# #iNļYV ϧa68>3ӈ?ycm:Q^ 3/K7<ˬD_nC#ՍfO=X^d!;yfp͹Dí,iܚw>aCny 䝴p..^ ^Zr<3\uvǣskj|5fMprvYAiLdDI H3._#NS @^QZ/>v?zԯp2lNڜ,yRLnj0O@u1+n.[AaX .^eR_yd{$by띹y͗^\.^}~HGafcao WT+B އC\4s+rjwң8L+ ! Rb9qWwDQv"Y,EwUR\0PZH Qܳw_t0Dz|2N0jҦ9;XQFZ=+~iA?Sг NS|oINFExjuD(EQ״#JWqFPQ-!!ۮ|@w(n!pMml)RzyGQ<Im$:)呞_̐,,q-k^(ǰ9!Jq`%BbHU)Zu7QMPUf7Hvmϸ(fU/QZkYBYWF@[(:ʓ|8EwH^iꢨ5mk\D(ɢ0lOizZ)NK`s {guM؝iԙmL̴qgXCSQҌG,ɔ(QH$} <]p>cDID} vE,y`INC[$L=$$  HN HN HN 9 9 $$ s T$&f4"fG\ѫ|gz)Voau˹£G0SGzC~g(ⶢRN- ^8P7z]Vzljy8P4.+P@r*44op<ۭaׯYI\mt%DSPXфAN3Z26U3>fֹN9؞OX )V*jw@ʮrJ?#f2-D=}'/ ݟ -VQNt>U&'XɆ&tqqQn9Y+*(D@z,g!Xﹷһ.$?p%BeA \_<>O>[tW909*D˙J#JRNhxl x 4F jsU"K{O_HvV W\I$?;.|{N&ߺ9mW)Ϡ,,,@ε6 џltn%A+U!wmH{ٯ#g?:_H8Bk@u(}f 1\}7g~e=p_ǜچM, f*wm8&9k|,eoث0,[SHCzKoч4:2I 91\(a$m7pɘ۷,HO'-Ϗٰ[+ߏX;DS9A$@pk$ cq_ow=an``L¡C6C_"yBjE@u!7[iCl~cL<ׅtЊPyNf錜ܣoP6SA,ٳgѩe$rnEjֿt=G{tOaޟ6 =8,ƇM >_x W'ു@ >npMP1=L$vR7M_NN/rLKE;w'ˉb291Ĥ ;d?/ݺ3:]"@(γm@B,Jw1>7;9:xa`LXNH=(F%0Nh*[^uen)dRrׇO9J9sõC5E*[J#fU,'^ɉN9Kp\,cO (zBB>߬nDGV1ENr..LLL fb[Bѡs!Hf;!oϜ9/(c_C-//gdO::Sȣ-' E .;9t0L}}}SSSWWIKg xy3,ΘLcǫx^\)48 y?D[[8,[~6,rҋq 4-(rхhl6[$Q;엄'C!BV4\.7'իW$'qEWX^^'Q1!![@c]rۍꇅ J9Y 3{8 ?d"4˗GNXIӶ_nݷrC2&' j08~Ԏڰ?S>r” DR-&cVc%_ to/ˡdն=wx ]\8<_+|Vs9T;ShK;A`q7-'ξBS$H HN 90 $DBr& 4 ѥrUʙdɤH%+J9wArtR) 4JNjK(Dк(*->:E(*09/Vo;V9cV$ T)'* ؊QV$$'`rRa&M*jJN 4ʚT''*t;E6HN7"Ahu ʉnHeCLNT*vQ  "At$'H(98oDE?\QMv;awKRe(I$d-!'ҩ`(%\ okŕ2(1Uwz}(쾤w81w{\b+H$K֭%R`!tiZ1T֢(KRN79QhU[IΠ;[!VQy%FcR>46MFbЙYkϹdUVKC4 9w$ O?;9kQEW2r(׆CG\]|qԉg޾ONL]?q'N9;ūdB>`(Ҟ5F9L\!ON!P/> Y]!3zA./M}NYrs cSb6[DfMnm/4͑bza?8sn?<ހ׍ 5O=T"rؼp< ړ. T''աL*CZ6X3K{ {m_ DSaO$s$ѥd&qyJm''zNΠߘ^r޼aAol[˹c@N 5$$'fsE<YKjKорAu@qbqMI3d`qI;)6YUm\9?KrpԘ ͕Ax k,FUQνK6GkfS̟ D`[ڪ#qIENDB`PNG  IHDR4s{IDATx^YlyǿKCJ"Em$E ny 0~_AC@`%ȓ_Hxwu/ QDpsqΞ>R¶fKZh$.UtUS]j_W5MFݎFpLHLT>@,cH$nq`0*7Ft(4Mݮ ˲`H$BȩB ĈBxynS:yT.i5v'ۭaZul0ؖCŭٶ,SJiZmSs:ccvۢaăRR1<ɏktlTVaw37ޞ5RnvXi<~)/>P"`H&SqӮɑjn3욦EcA<4U'T=7(`38"H85Mڂ#c TL=Tʀp2IR* HIJ% " j yPtj^1ܾl6 D,sD"9R0"K7?GѦpAJD< /-CO@B,&>\ \ĊBGOA^}BhhmE{?sx!O=)Rộ_!60mwޱ,+i{)!'\{ހ. NZwnp|D@}jhxP&~q?)$({G^B?sb%p_rRģuݡͤb4towUtG=bЏ Źw@닶*@a<ɓ?ˈe#OElx𡆵a`pD&IYSF\*gz>>0Y:XLLL?&ΗD|u\(3@5[BOOf!1Qz zF߼̀e}\~w uzRz'X ^%ZomT`tOZ HaQaEb0F {썵B8}1.=XHTzNr3h4^lw^n˕*dG Z0Ӵ~Z :AxF%{RVBYRp&CԭB~O=1_iZx/-t o4H_)ؖܰ,48끟Ir/x % NYlTd&v%G|ŐDa~Oor;6͇. `|UU߿o>@0Pa߷gOM᪪ 766ܷoߚko۶vZHwM͟|qMUV}z՛6ml۾}S;**co9Xwխ%&5 :PhdA!v)"dL=@kwәj6x)I H"Ō))ZG)^\TXnCN 0^FNa| ju0W`,:~TV57Ȝ^*/ZiF4 =7PPeL6dw 6XS"=t ;L=J.(op3iGRi AB( *Iw96} |OTgC$ dN.Y rC]@y,H?Hhɸ(%Ph5SOL>y˩*+hd=:.]c]>AYܲ/J~bۅ=T`}q|&?szv[{<9dޭD"4:::aw&Y &^ӰMMM:}GA&"_j EqE~mwv*F"lXsG k/5(,;Ge\@Cx 2K>l'؋z*4~ iTImJji!>lɒ%7nܽ{ev zׯYv:X֞,gR8jժU囖.]ɪU+ڴyÖ[**v}t݇"4L)S]s="z+]NGk{gJ(fHtEt-///E@yor৅)F-W{ | ʄ*;.% F +ICR(dl|I5`pab”.QV>ӂf!oP6+VW6H!NXok'z// K_2lG)#Ge00&.AAiRݾ}8/uuu[l6Y#=FneCJi9ŷ~W[-;;GLMFud0LjL#rDpǎ qgDR AT{?d/Tn WyuԻ36)NC@HĂEZ$,D?#5M_"ޔ!GO sSڝ.>xYj[rB[e3L09F:v#jS Bj^#x]9rPUᔂJqz嗱=Ǐ/~qwϜ9s֭[`pQd/O<1b+N}Q2?d+ر+/S#FUOw95X#*qr"^8[cJ(žkm:nIOK8ٱP_NTƋ˰U;mIIbJw9ɲd2 4 Ol<~j_M|ұc]Y%RY2j*>TSńD&{>35p_n+ܲmɉҒ1F74/6ehNfƠ]:(DGkdc|3uZC߮&-*TxYw5Uc{yd{s& E&dEl> m>4 r-1Ӄ=rdĿJ ?2e zEĀar@ ۸{;V[[Rud~[) H+"F hPb$*c1P-q|sO>ж;EIe^2DSNfPsޗ䔅P\t)gN&UFa3Έiʠg0fL>g-ONM4r2B'a;;YFCs}zGg$k|@)VV6y}g~1nq"?.& 7äB ިQ:qE2d9Sy=.ϋ f$k[x#gv[O>?߾m;ïsя$c 6$ WɂnnɞfP l709k׭#o|XDz1WTa 1(ۨdߋR8=vyW[EXMa=fnIK]0:_~f= .z>.I#T(H5,T{Ɓ p`0$2:98JVq)'RasŅA6荋kM;65We)p˖OϢJ;#;o޼ޚR$E̎P+Wd=99+ⲙifRĹy8A=z|aޝa_o/^nw\W~٥#lN,۲J-sk+cu–g_=^[%&sѓ)bHQfc/^Qz_w~q+ޓ!GHjZ*"% i3f 'u*_?V42[4R"e1ƈvCI,,z>dlo|g,G cJuƛ.{|+Y# v|r['Kq.'gee!Z_h-/w}ԇ hԈ¡jj7R (o/YGuw*kjqN(>g.t6=R揚KUp kWbAg9WB%x j0 Byx̄GjO=` EJ9eVtO芰3fݻ %?5$b-+&TGsbJ=t9t.׿+ĩ pxP kzb_}yR|[UIr̦ܡc4Iq/>y:9 M{ -2h6(b*`vhes3 )ؒrBqhM0#| 0D .}@pN&WJJ*riu:m9Ž/> RpNorHA~}e)<$3lii1p h>ge!HǍ)W .$OCD:J &M PD '(h# j=+8FZ뮻D$H)|H nIۗr\0InDvg:;13bZ m34}W\9s;܍'OV9ڵƭmn"R5636fq{_#IIfEQ a22*Ђa04Y`k$f$s d?sth~M\6+=֔B*'C]}aZg$:saaڂ[?牱TGŃws*VyyLEBJ jo$m8wfirŅ CzsNAgvAv(ԩS1\N{B_ aڴig]srHDcNeJb/qǪĘ>d>kXozqؖ~!9I8?#‰9LxFY2T}`X֤MLwƐ.>hNi;P~f<!Լ!?Ċ=9 IfhO=O,o|Rе@%5 ~@JۑrI̗Ԛkff .:6]V> 5dF\rJ'Y~KҔ>a Z3Y 8b8y@:gR_=DõGaqr7,zq{mࡃ#5r1ߊTLV7i+0 UEf`W__P[QX3?W_}?)H`SQ'Njjv$VnZ99 4ڔg2{Zyóx]rez\y/O^lܧݧ ZkxiM< $nԼ诳2m&caMrљr0" {mYCqz>N2$δF0tw꫿be^,Xp[C '򡽳 yso%8 ;^_P, RM;H搙m۶A$8`T O]"W!M!uΉk}T"q!'_|GY$/[ŴwiHQDM) i>)T^vD٬% Ǭf0=AoPf[-wp ŷ;簤Y6Тn͒) J碑$ HJM>PSDUGdoup=-R5ZMw=NlT4:lNHKM#^Ze&WT6B{WM  !v#09V؋ދE I Z&NI3lFElBXVxDxWONv۬l g1sZ(e2Ƅmtdt0[;SBJ[|)ќVvyn&AlDN6'OAU}U/X ĉ R}9i˷z 2Jڀd~)F)O`q 5?NXa~?#-_9vB/gHx^8>V:AR{D vw̖n'un] 7OX[*y)Yyzr-qlT hR#RATJv-1Jh=ޛu]gܷ^( n")(,J$ʒlrv:=gƉ3K'N7=IsOD,ks$[{}9&P}z{z NƂ0]@ΥlfB%W**!IIy+ւgSdf/pNTS*~qn\OBK7ݧbH #-*ym;Mwn90t3HJ VcLELٹP]TMy539!lպk$d.!l77?EO*E/)\LV;39sQp'gw>^^r: 'X$L"}oa~%TYmx*#h@wee7sA0 0 |\UeMP)1g["ĴEBRlDiS&(%Bۿ'3g|U0(jw.ZvR'P(o[R\IӔKȺfmu^CT.iwk'X3"* 8[+%!E PlIr,(y9tU$o,i=q&i4c45-fy45_--lZVFFoٸAe<T\ ,ed}zL)(KaK⥉RT(18w-wk erp9s '^qӲ,̏l bK/ylW|VF6L4M zU8'z|6Dtf BF t^b蚲zUPtda<7ex 6L@ lk.W$"9 z {#"RH.+HϜ9bg`'l"+T"9sԐ銸LwЕ)a97\|` o(H 75kj+رTSv2:J=sPmp'0hkm_ۗP9 '$Nb" B^88㒤1˄t~݊SOr|@% IFiO>.ٍE?O\ee%ܸ(~^$|ms7((öm&x=F(W1#9U`2U`Au' 2`K9@xi0:s/fJU ;u,'-`RVQ86( 11.² p'] .95${vԓ?~wl}[QFe3G-gQW5KvwlwЯ ;Vg(O^ pPFeY_P]][UU5ټ# ׭^Cy=p=pmg劮5+/[ȣ{`nJĆ OD,Xvi/2fD`K!#QFιN̍|&M[5 L.H4msmLSH‰JgS=:]x"z0Kt#H4r]0 HL\&[[7n@e8x͊+;(3Y;J5Xaezf&4#,KupjEo!dxh |^;\#`KH,54*=9(9"| . *ix-тn`VgʩmuQ0NiJQ eә4F"rTL=G5g<s eayoa˖ .W r.?  A&l6W *L2cMp{@4 Av޲sDe%'_G{]@㱷z~PLVԷ5{ E3jBx!E7CƢ,9neP2'`e&ϕJg+CX,T!co*RTc1~ (՗;ƪ}ZoEOq⶞k6ݱk{qQFY!4䬨e2bpy5s4YXѬy*aQF5'"xE#XW,n_\w<@:$T2NU!)r+Sks<BտLVBV _Z^UL)ռ:<(e)ؒfҩmE?J38꺐gL*u#YHBÚbҫJ)g+LιϾ)'BD@rK3.꧋H0޽6|50ء*(MsaUA[@*PYI+V))T (l:G"q8Uh69ÇGD :#@ĉ'pi](n*bHNrB.;y`!@>چ0 x3m< ɖ޶2#B ?Zh~:,crƩ"?Ki%KF 7Ex<^ ,n vp@F8 !\(pH`ciw|%:ԕ %8 e#Q{hXX<ⱇ>U#EBl#yS;3*]ؔ4LD+k+`AoٴP6=u~$ږio;pjuP弚=8gdeֺc2XzU,ܯB^# T7z̫y Qi[lD;{T~RR}M7YRu.\ Na{Iv>@Vϝ;s|lU iw7FB8TD} HqH?9EWEnLrJ)m.RBr`$vВF!/2{ĈW>1X[(`Rhs_8(>K}oJ5h.mnu=m+mްu 6hb /zQ7Q'y{Xt`Z((s@nUW$* 'EA{fxQJNijP7̉ҲrQ凫@$ !DRV7l<6``q*:ih r'YtƤe4,Մ|!o [Թ坭lN](:J7o*=bPC- L/M!(E%՘D! 9-J&B0C $ԅIssaD,(P BTL:-.QbTW?8镈 Q4|rtvfIC\ Cn;}ÒsJA;wE}W8i8+hZuaTxC͍uNϚ `JhF \%.Ҷ2@kTs1 h/|ã%AJ5j4mnkA@˂u|76D*$I" N?ȑ||0rWzLpWDZ;o@GC$i7|ՠݰOh~@$CAz6gU;N&(fsl[fȘLCgEk6Tȁc%e^Q-K[_bd06"Kg{NBw?/-DD!=I hv+ rvxryEu k75t~O,Z{g~ǟ>ֹ+ݡ,g#]GFz3J~`ןj|`R-A'=r:>:w|.PBz |"e!$v[r8Y`K+  lȶA"TY $SSڡ,XcOp>_mT{(?T/©~nqͣQw@77- mZ2?. {{s~绾h|w*;ɜ{=n0|j'?T! lZv0{ %=B$$$(5$d*9m͑8I(rim N~Wx ;_b #DpPoM #ܹl%x4>Y P!P"Jc5~=. QZGSS*T@xUu}VD(lMXF{d$BAk[j$\U`&r"^w@*Ѥ߇Y6[]ټGp/yYڎ>Z`tVjz)Eq+R'{h3?O?`TUMz"CfB2OH4BxNݛfOiBl͐?u爪nVU8\#p^ͳ*_o@pnD?o'z)#+g ZdyU߈ƭAƋM֙=p o Ϡ-wȩdQ!S{V ŋ#zavA6 }Ӟ}vkApd{w @xwAS{) 徆ttkI.߶iKgRMюDRX"sa+2#dHK^?MUl T۞ ;K ß"^YWn# TMfj#-Ȅ<Ɍk 8DH)Y('u 귾o-hIQ[ҫ7e Ad ]4գ~ugҿ1?(<)Bi\R]6~?xϔf@PE'{>NA%ku5MDrAhB񭩬~x~B&n@E͍Bw @BDJ|ztq+z=}(ROɬw$L %?"6Ο;?LJzGhohd:D|׈L*M tgZmsOިf:~pU@M p-}0<P?I_zn3D;oNs}U˶-m6/|wN/_ٰ+TU:":s?}򹟉OW^;fYn"lh{̶ LEs@Ke"Jne(ᴕ uө*Bj@YHӑjw O>yn<}$8Uu"*y#"iaҖ온i]~""}GO,]lu]Q%U>{=z}kq{U5_l__$}`;JP>x+d % p F"YsZo μq^b֟e=PJx@3BT}~`(#|U"BMT5NzQmdI5n3X8Uy2JEL/_BI/~6yaUKFNg\o~iiiyod2944zaWAQi4n7KDN,VavL 0oi# 1]PDEёӈ (M7G?@__Sr;hѢNDڵk9 `͚5?ϝ=|fG? _|m\ALsCN0.d4}Uf`jc:K&շ]@o' /%^yz&A G?1kgqN򚞖[nlXCz\$@@"{ RSG1T'-F6lDlSS][Ág'NL7}C]6mrMXx4MEQ.²,|#T⥁?9+S/o2=H8:a !|3$Fغu+LO},/['{ŊO:}m ̈%BMş,EHs?}, UB65S31&s==% #A`k^ s8q wmjjVee"yKr׿k>USXp3yJ?"a(Ԡ;tdĽ|9`EH0~7Yʒ[֚|# ܻw3.0ēʝ?/'jj D5p&`xWjP^3 YGE9c&K_~_/AvqmMEc^uUU(zߢ>tF]n޼-iJ&-a28xB{]wjjYL" P R1lC!앁z`Js)$ lr8oVTSE<M#8M鞜x>p^vP* ' /y]+8UQDB8*@n "wK29~&ްa̗-["Żxs3;װģ9C7(P"cA ;*z_hX+O?ݧk޳^uSwwe |.&맻o\c6/^===> [=*_y"ڶm+PxJ4.Y9{nM>O8Y򡖖=SZ6=u$Ty: RP79MqKlT5ad ,jo{yZF^=kyo~)]]];w*+Pn]v1eLt:] L7ݶY++C֢:wَëٱs"ĕѣG]x(J)i,:d }A@P.%P:ig: rUA  /ЩHtx뤴v^ↃıG$P UI%Z93JIdI@ZUxwﱍm~ }vZqy VBJ"ES2V>f9U\@woWږ}8 vܵ}o͛o+;w<̳wﭷn2M^o}3-g/ݖV>ȰlqؾV^0KJJ*\Y|wQOr=ܗT1զ*ݳ#{2͒Ua*LgݯN ApyX_ۖ6H0tUW.3vkLCY^_lVٶʍMՋKLuʚN|ѧ~B/{fWO(Jo:wv&RGGGN͂}I; dfв{I `XR@!)JDB6N̔b.^5 CQt&tY;ޞ޾ZDc!=v˗\?ydU xz=~?BlY-om6a!Yzr,%*"?vsG}H!zī, ^8&> %1pa.bEoA]{,i?A>q1'9ROMM<0s"tA9i;-} ^wV\SSsMb9BnSS{{{#="dZ@zt>}4qLz`d؃(`A,d{ӛ.p4 =!r9.B9K9ػr ;PqHHDцWvl;h.GF/hHA׉݃`xéS'"D;`@էcNۡ^'1=ByHLAnn.?`>sϞֽ0=5YqZXhCq ^-)ũLYE2J"q@T$beA4HJ^8X& nٲH Xi"bE8&KrN(Ϸ  tD2m_sg0$ZVR4!;P;JKbW` riɈrHQRR-Ayyy9؎9BtDG0LK$Ge6=ÄϟMCW 3g@H,n8v `:DgAniW]x;.Qb+D ?|rksCHQa+dT;FY ecvx,+4*ʘgXš%ٗw-֙ hR9S# mmGclc-$G"X K&<{,s&#%# X1u; _|QOK{kspu.[opumt|V  5 V4P,iɂim7iih)=bw;m[vۋֲTu:e*nu-lQcS_hx03C'8ŞUG]8F`.Fո~z*&L xӎ <و*SC]Ƃ><.z ^E$hЩ Vo8^vK٦tuv`,'+m tD%|x-u9 &3X.O([q$)4%|~Җ!: ©5. . 9K蒓$)e< f(JԹfmeΒYAclE>g]ݍ#YGƦrZ Xo4}Myz5yҍj3s=s=*Fĉ1Y=1v9lђեQp0QEBAT"NtYIav v{e69ŝdb=ls׮] * (\V#^,EBߚ"m@U1 xqyd>*WoЫb IBJ8 Ǐg tEPERNls$9f&[IRvc ?Xתmʂ+1p&R؂~7ia utaU,u  SFX6FϓDT#geJ2TW1aqJ`EfffQ<3gΝ7O>9>[n!lPL$eWZAHE!e!e!RCP!RpY4X; )N0Q"Ӣ876󕝝u6Y)EN5dHr␚80cKi,p0&fPJ+4"brY7B !^r]eՄ&htp>}iw-G^]$ 48hhдB̆Є8B?t@ܝ`2P3PPq׻ Ϳ~m<$P$  EQ*΀H$8EIXL&*ldCtW@Xih&hyP.]] *M}s3%J΄`WLIMW}{R EX0MA.'zʈh(ktZq1ߜcKӤ&,/ ǓY\-q)Ɠ ʷv5[yqRva4hF9@N0R}LE A ! _{Z a0t!NWFz3_} o]v$ Vp=Q" Arh!ݳ""s*)c,dY<m0Z B[_MMY0)V !UY\(q0(AzqsBCc4 "_f7ܨޑB8y*NEPr@ "b J)04[VquRH !-#i1Ƚ-XזQsB/? d.h"!@Ԡi >sӵAZDpWSN%°\ە9n{0$ :`5@# Hu 9+?ԩM7~{tYY}ߟ;y|l=tZFqO/[1.}sn~;/}C *4wFF44J-}(T*% E(CU`&AT9*qu-loY)dF^6۹Y듽~6sG`RЖCY 05hA4X03Vf #?"{fdW.\.Ok,7>v℘- NRD6@X?qd?e7yz8 .x_8+\K-1ȴוA0$Kv{].jsx !ZK, tV !Fm7k[N%rdZ!r7O)d @)R\Y|ߛO'6L} ʋ;SMw2mbݱ6f,M0M8Ev7..4Kۓǟx\P9)6.o)zA wsqys.޽ҩXe%˅+/W&[mǶ;F47r "!7Fiv'HOB1';??TqMn n<}?b߻{IæKзr{_,^%LRJ](lfkB4ol0^mc!>9gwЖ<->'o0K!\ݺҥz_瞯6/šA{ÑB|ᅱ4pDhb_suiIK'޽p Wg}  Di*/~|+xjĭz} _/}Q>{җ|H|L{)&6)b4u38z{ku]_8^,{ً`)(};>z3ha?nBW!/fa .I,6Vktum}0Go!0kw[ i_ V6&ӝtma oZ^{U13I rN0'{~.m>{)_)!Zf]j [NtӉP\4땍swuuPMя؅=E_g>ڭ}2jBr~쪢v©>+xdu QN:U\__˩FkG}nHzI ^8w݇Q alh4[w}moXybW uCR- ͇~nKչ{z"Gq؟=q#@̪Y<x MR"HSB Gנ飫&`IG" ͺhS׌4aV곔ޜ ׆3:d! g)⪮kkЖWz" pB8}/@ S卜}P;}zUXc?B/ĚYu]O|djZlϩm]}jkƲ٫,ͬfv5U'lu}y007w[8uu{89S'槓hVsѣu3g={ViB/Qvegn;3Ni;k9- c̛vn*`ֵ%N&f8:. @A` }sAif:׬ώ Xm|ki<=W\ $L.RwDv=ڱfո4ͰunVS5w_=TQR=ցhxK)SG?k;#\s8X;znkkBZgJmfs!S'O8yf+k),.,glq~~:ys|dh@؝v@ed0G?_<kRMv) ꌴ73DZ(A }I#P n^bzask+ f0t8(T@Ool\BHeھwwI{ 69# 9#\]8iF3 f ݝ&c4ʬ:yjqƻo:~7f2_Q-U6]UZDŽmے4M y H;pnSͬ^R ZQhKfcwq/x= 䏟|iýͷ@B )41 ƗUUAD)\$AzjyqjW\~]v&}U N^Mp=* \h23w7P.3(U iʕ?$)bۏply9CsZXRD9ضܽMGiRP"LF 57̷KIENDB`PNG  IHDRaIDATxڤRMkQ=LcF iTPBnDƍX+ܹ+m7\(h@nmjl1%M ysLJӀoq|'m{\_?(nAc^&yD]iZoPS>(;]HO0 FܥA?[d0=8e9_b|Lk_@7p[%9DXX ӗR:o#jjedb98bWƆV%@43%@O*.)nWW]olAU#x98gWpr2t6ji *Nΰ.:FC5IENDB`PNG  IHDRaIDATxc *o@a|\ 0d +H79Hwl@LLL$P_ dPP7_j3~0mv沣5 66Ojhh`mP ejt e@8A|A|0x`l_OP'5%eLL qB0 bҘ6PIENDB`PNG  IHDR7IDATx^1 @EJd/`),6 e6{kQ<|C/tOI,V-Xa?',{,"+NE?ޗ|gނIENDB`PNG  IHDR,tRNSIDATxczQQFIENDB`PNG  IHDR7IDATxc6#y3f(NQG/ Sv @`3`sY俨Q,3tyȓ `3N20G$@ _ŠH@|B>E8 $ * &a ~AorȭԈ>iDq?PfIENDB`PNG  IHDR7IDATxc $F7F_5tS }tԿ1)QˁJF/C3;CĔ8pэ`QKXP .Dߋ: @[1}Q`Q00u5*CgG? g: }3 _Q@y# E}cF77 ZH.xċP@11pb0Y7L3>GnNo}IENDB`PNG  IHDRaIDATx^]KU؝Z$!YbTQĵ_oU \ivBJs2L&8INw9תk\9uu[W4]B@5@迕p~叟{w3xQƓZ M ړ ]/pqsgj/錝C~w oi0,@]z7 ԍya8HY_=K[TUƤ>^DUyIHERV UUgsT<Ʀ{5WQ/ Nhz_G3ѵ$ `%uLP575N< Ney7:O2dݒ|n S X[9?_U7q.":8:q0m60L0E4P'`87n;@$w1/4B}X!xG^(˒7_\\Tj*/έ;$vT{kk3GE0֡(J_dE̎(1g__xI̺XLp!w95\%+jDt%g9τ&'9c O0T3q. O?k{c!Y2:?(*``޿TPIENDB`PNG  IHDR70IDATxc. * 43!!S DV@ʒ^#)IENDB`PNG  IHDR@@M PLTESSSSSSgtRNSv8sIDATx^1 B1Dы[qS*ՁK Ar@p?6z>AKXA8t< hwl4l {,`+Sc(74+P8 W#*IENDB`PNG  IHDR w&IDATxcBå oL(@ 1[ñI9 8K8! ~R@ac(b't$4D hq)@BaPOJcSWX*)@Mq& q.:LV>_IENDB`PNG  IHDR w&IDATxcb 0b&bb+bC`LR @|q,LG1#+lD4ŧX{ǥP9 *@ű) VF _ ls-&y8V>A@IENDB`PNG  IHDR eIDATx^e 0ں@lT0"(t!r{>Y10Ɋ+3K7cJ;"FlC;ӫ )hqlҩ3 dPgL*?<-t[8IENDB`PNG  IHDR w&IDATxcBå ohb[Ml@|/@G01|,C@ CŽm |I\ݏx?.@q5ű)+@@g1HR 'IENDB`PNG  IHDR jcIDATx^e Q=7-DEEJ?‘e0Cԅoل{@#E!H:S^> S4.4d'p9>/avIvK`7,IENDB`PNG  IHDRddGkkbĻLJn7ڊ &Ɨ H[d* S^$E 1if3#&pH 쮃<[!➙*!q 0#0wNp1rz6w+ymrȆSH-c`vZTXU\7z!o1B.,˳ .z 77X~d%!J3(C)>XG[#ō(?E9 Q<IENDB`PNG  IHDRӄ<.IDATxcvx8d@@$@AE!ܐED!zDd#(Vzτ"IENDB`PNG  IHDR7IDATxcOAر(`fHx ΎFϪp0ias R`e!M0?L]:!Mo2)τCcpUã!9W4@|VYHMU@MIENDB`PNG  IHDRnM"IDATxcO2Z$%IԒD\1iKrՀ(MȜPMR) .aţI诣W&}|\ IW|&gjY+oeL硴+-RZwti4>dg.HcbfV? yf̪ O9<3ׂ d댫ǂz<\ Cf_s>y23,-5@6zS:7@4)J}PD䒔kAI{YKH/I@8L>xy1.IENDB`PNG  IHDR@,ThIDATx^ T=g0P(u+J<&dl<0+B"M5R "" r@8Ǚaz.go7_7ͻgߪo{O5"EQ(@EQ(DQ(EQ(@EQ;D] D\3@_ngg$<@`<0*y'777O&3X2@(xw0_,L^IZ9y ď[# En _WUU]ALj&qU@?+L1"{@G.D(@?[M6= 92ި 0Gng? TuQ:yR@sαe3e$'1POw];1FmWk* è,ß9$iȴd2mu:^A ӧO۷o}#Gb~}2/[AEIM!U <uPx!˨# ]n`06PH#&˨V D =NߥEIM968pƌ'ЌeYdжY]Dn8!JEGAEI;@E~9+n171qߦ"eeS`sU6~Z[[Wϑyʼe%W D`[>r%>D)6H@F AU S{ '(2m\qƺ\f̀i7n<D"1wN&#Ӕi5 ,^=w11N7;Ou2OgMmmmO;L;L2~5s?k<?l#|>A*e ÐɁ{a-gˑiʴ?J&ik>_ν{6<\eO||G\C`N2뮻\yl3g++++G#Yf !"ӖyDp3soC޽{irhnDw'' ֍bQ )rYO#@3'rGXqxRǑGip/۸#ȫ2 Hr8T b`B?Xhy|;\k{6w7>*)y ` ('ɂ)3=R}T؇]%+ݻw-$"0;;̊ n`ChѢT*ud >Mj vqO֗qw#"*0 ~*s=crsK3a˸#왽ƯX;(0^^jT3Njѽ*øӿ2 F6yȼ'޽g#Yob (p%D Bs7&5XF 1w\ VHǃ5y ` @[B Ij ) >uog};ӠÕK,؄n[MHk,iyhB@[ {wzKwA!4lP1#Xs9|N;}mիu>^ [$5ЄP>+Ц~{sr׭q]~x4fܴi6Cww׫ t}so{Y3+ƵVȴdđy{ ?3<P*=q"0O3}7[%^%_,Yܖg|,iɴej'R9&N{[ť^>.UZUB+׬PPV!W=|Η. [ZOҸ-(:75PK>aЋ~8W]PT4G#S>r9 %NeS7;` -Uir%S=NKe `ħi@h_6t@g߅>ChD@@ *ৢ6?{~@%xدT*5wJ. O\kT`Q\ @Ty`C&#Hb"~ @'lE]>n @x"w&wGS!k'<?(S3\p r:餓ΔǑy9,WfA G|A@4/, 73fPf(!I%O)?''@Tms|! _`n?K/|Y~֜Ĩ2N }?@GLF=M*@ޢ.jfs[?Go;ѠAWuy?8tAx.8͝'w_0G%XWQLp&܅^D+-c]$yLOt3<SOr?<@\w@t {I%hWTw #ӓyɥ]r( >^XU|Hw .LWRoTyF!0'S :~555777NW:7oj)YA~d*h^gQpމ~#͚4_YYY?n 4=9Sp}xDM#\L@<}-ϦyL ~ءC~/`yQ' Hmf 5T/[lWuttu0Q{l<ǯ36/}`:~yp8 :aN ?w5Y@y8zҥֽùg=||bL c*OD0i@!M&MTظY;vB4{Uiqe:i/upuG[^ʹΏP#Ç0Oɥȴx7B0*꫾qIK +/Gܸvuu1B:pү[(btouMx.֜`-|̓5Qxkβ0XG6l?ݶmەB0y6?:  ?G+j`JwyQ*zvh_"j"M 9jg#u?8~6 @@pc&0?aw\!#y?NǙ(]rYm*n1Q;n(0>#4I^crqc=\Ogwܪ#fK7ju\Y:4Ikc}X aÆ](Zwb!agLҾ8L_~y %܂;:Ct' 9OrS,!2ڀ!rKX7C 48+jmm=n"NT7k>0Ped5|BAYXe\Q |thA h_|qkj@I]]0? ~oE@U@#x_v<\rj9 A?/T%A ikk#I[͛7Xm NJ]F8klj+g@ۨ=,JE@+_`0jOpII ,D@;SV`Pm(~2WG@ ;L0@'LtE@ 0@hG#}gf5ϱ#N%JLߡd3P~4E^C+`_ک?9ޗ^>gyU`@+S,ucL;]tOiN4 ( ~2][T*AJW/w0@_wkt?LE O,PrI*ʽz]ڤ#2`s=yC&~oxY0{z9B z =30 J68:$:~duzdg#DUM-tj<mϱU2|֊`we\&ˊSTEPݖڵk y\Lݻoe?ζ}P,L>ɨeep'ǝ_k=|ք\[:Oh塰ç/:G0:@XfVa6R9AD>mԗot3%#RYޱ 65 fH-i+lF}aSrUA%roQ-t#BVL#>?Vco>rG@)'Jf 2Vst ^r@!14OGOz?鿼VXY~ACDjW^:O*2W~oTi<@AQ?(je%ԛ< vA.MAD@`[LÃB}@`Ru~yN :[@̋*@IiZ =4%9A!XX_ Yq y:R/@ ucv.Я@>1s> _< 0A\F0" ^9f30^\@D[ 0i D4;u466~eeD7̴X 04yn`]zG=OG3;#@AP~2չ  ((-6[bi -;F˳sm˗Ы_L7Ft  ߳UM {hQjA q1i{Fo/0P<^6?"eg D#کc@_څ  @  @@  @@  @@x7dIENDB`PNG  IHDR@,TYIDATx1 7̈́4G pp$0@0@0@0@0@0@0@0@0@0@0@0g΃(LLTQUdMU(a!C`6@6Űp 06&F#c|,ecˇ1yFЌf$/~#G3{51=ݢIOwO+~pILP(dGxb?RX|._jepx#-@H `9x&x$rǚ@H ZMH $ZMH $`֩y$ $L-}I $H@X&> $T}WТטA `"Lڿj7k+N4ϻL@W#{}tx Wiݱ%p8"h*-@B ,_PJb @!/'k ءh*ڣ@XW H `5]Kv|/}_I$=2{MJ%Lɤd9xP^*? l $vE劅Q9wfU?- M}$5= 3nӭ/ z!襫@|nb+~8&f;|+G8 ,iD,CΎH$>~&* 4@HZ{'s,=AFyH "ٷj[/ ?{ZW@f٬Uq~^@HǻlD:A D. ~?H r@@T@ $?FQEzF@`~C}}}->H "oCbď@  r@⇞_3j $A=bZoH D.H~xOIqG9 +?@~A砙ɽ? @y %1YW&${BV|F #?_[{%mP~_ս>k߿-{ĭ@Omӕ/I*]Q-h/i BKJ.t0=Ak#oecS\Lvj+:!kց-`:If/H -i@ cetsƯvYPcvA$Cߩ!0eUGc` ~, ~?,M\YXWHDzO<( pu u @VaӐpK[+pXj_iG  @(g/1<?Kc~{?Ћ!3?JfE?9yPf؃VO d `=/Uv2dG#b ? y9 d 7/qz2?͉6؀ůLyQB\#qi.kF#666,̲ EgYUSwsQ?i5ګNm6[;KSB14,N5o0u{<[}ӴF[-uh"n+,[B̍op,}6A>oj/jQMbU2˂e~EߢmpgCn |ʣ++o{ڱAncp6fiQb,?}"O.sY]~ќ^G"CaL1x֠pY Xd@G͍7ms P] Ah8SͲ&İ$*.vޜ^cF{XԪ#?M0#~f%CYVIYIxCi Y2G{Φ>>8~e @Ak#>ߊs{<H3 6_P=ֶ.`ګo| [E 8Wks_-(by G1[lG,HQ{I j#v2qFdOKT ޶o۾ .__lSZt4V*?D%Kt\# =Mjs`&jT^'%kt~DVI q(Ծ;9MM _1jk#>vvv֨ %2~De#WcOrnU|%5y';A5gs/)s> 2AQh%lT5Q,lXJ^]Ic!mmLu9Ӗ`v%tlDΖXeAP,ӹ'H*r)Xu_PF+m ~."Cai<`uDCYf2U" 8.`K5/{t1RէP~Gݞ >g y@`:))Տ+gs/ԺOyx>c[Vk5d7l;(]wne"1 fߓիJ;5Rn~>q}`ZglOtUs%dyx[WeŊG$|ǻ> fWz,^X*mWkjytY q9$C]&b?Q&|u?mOl=)ߟ e3oGȰ>eP0zFb~].WKOIEwuIt/6I%DϷR |&Isş=M=߅3{Cp݇rʩ2qgĩ0oJ ֕2@Z=HHJJe>O .'`d? ڕw5;P+dOq>%`9t0=Lsv}=HQ0x<~hXU~ҭU+ՏBڥ^S<}@GD"%$o;ӏ^ j!_?*MA@4z $t+++/^ض+ bCϯiq>Y|x ix]>,1$0X,&#I?J|oNk4-A)06\}N]`at!$c v8ۏ}HHo8#8+bfN|޴.{i|n[^]6/<H3%A_ח?.I9Z=M;J֯o]5}|]RA&k_é);?7y$@X4ڗa{ľX=_ql_kh'@>V5'[v)}% $g]=Nl?H "Z^0@~x~gb~ $0gڼ $~UR/0U3 $9~We*Eŭ@?VCgQ&@w\|c@H -϶ O ,cpKbO ,Om+n$)9?E@Xr8f$@F $@H$A@ $@H ||r3gz2uTh4KfY`vmufXkb}zUQnv@;%wT 7*#VX8i*܈z<HG #`eZ$0M2%=w$#!o_V]]p6ZAHp:$G˲([0]c@ߵ^+K,h4J7uIhm$fBpҥrQ.-c_- ,R  NI2:Ad//:46 ; $}ؠ8P~R6HcͼfZ1mHTį@'v7aMMMl? oK_o@sҤIY6He#2Xubob t_ҕBW ]zۥ BG%s\,:X PV_al$@=1 @V gcv73No"B !@ ? @ @B0} @~ !@  % @I$P(I$J% @I$P(I$J% @I$P>ڊ2`IENDB`PNG  IHDR@,TIDATx^Ա@AGBH X/56s[ H @L/mu=                     tJc"8M߲,ǴKݺ{ޯU!3+"jeT Ro.LX?0*BtڧIDTTaLɃqZ% )am;<~ ,waICr7XǍPv&n UqLIun?޿~^)o'WUK-!9\1u n*D5m0t#A޿ 6Dzkz5jǔ_$J#D- )sn1S1cDN9k;`>@@Gf +=<8`Nyִ f(u[tSicژbaXg֠PPS 301-f1mo]v AP(l)⋏bbEg5cX @&M- B@Z@PH')mD%@ @v{-!P*DP_r8i@)5U D(Vtr7.dl\|bzP([a Rs@`b~.$'^8|@`J֧A\A}(+ECG}hjE8ps;f;=t WHȞG -`7݅s\^v{wM|SbGi@`hje6 S `z<] KCckK5=Ca2)_N ;{ka ( wa~FkvCҋyvtB؋+(vq0X=K` L|^@{~ &g]8дQi!χIm `ER2Ld)hy6 p@SOf9bLWÈ>`=a :p<:R=uBh=a 9װ1Z pGool[d{~R8k:lU90ٖF czZ$ UN jXdYfhē7q4v\@ ](@g[tfV[AǠe0ưd .p~G)` @0E^N^ cƙ՘](C>3е3@K<b`(S~~.ZLMPP^wuX,=?KW_7L>]oԩ:/^={Gss3Ο?8ZN\ PLO;0Sd`0Sy^ т5gJV V+9ONHeh1iXV Y @yxt`0|,`@V0CX2-[ @r ?#V8BU}}}+aKPhJNMF Pȼm}8<(q,dmqu}'#\Ӈ!۫=SLƔ)(?yyy#ǎpAw^̟?HNNFzf:&NM Q[z ҥKrH@7nȃL/kX 1iN7ݪU+Œ%K8b0*^G'M< qq( 8z(?oG-=k.pjE2R|{fffŋD=ܿ(! f޼y?C`[~=nݺŽm ?0Ȑe/8'+y8q~OdfR_/\t˖GYa?1kWk$jd2!h>HfJh f()GJz"˗o8%/Z~ш(:5DCt`_L!~?I.9 ,[v]b Oa7؟q2J18d1R={gb[IjT>'A%uc\+la -|u_"wִ!ҪDM,,L@{q p>8{FZ?S,zXSwI!9\d*nv|B !_W@BF(BjYg!`/s %c # &6͡@AA`éu~&jK `'qNKK[8Ƨd+p >l }Css$9O~~C`\G#Q!r㐖:Ţڸ`'C`w/,svaDs<'=>ƍG$:: !I҂noDzDGf " p!^QaBȔ')j,a]pAqX qV͊7lh5[1nQeWzf=- zpMBMxd[x`s@Qg+:t *@'®1]/Ds=V{;>#f7H!"GZP0ad8`(#KS;+,1ٷo+r$> \AifySҒ117% ݢ#՛ ^b,Ae = E1pqQ4:"uOH2Q ^E*Pg>2A8Zx &ՊU'q wxᄩC f0hwdum8۠?oQp 0kY[oCQPZ,͜yr.l0~ nN)<H(Jz#[3?j__΀lj}//,'F}yBQ J2 zkjhY`QQ "'oVwGLXvMNF5w:|x{kPkرc!?y,G>pRrj2/Zkaw=Ӆ w .`F\/Dֺypٻe}>*>?C8)W^]7+*ZK<icX|~^BOj @k2eC`~~gvldwX C2C ֗KװЇ@r9y]`Ƚ];mŮNQ%hiV'TT^BykPZ͆/ŖZP?iu2hkdZ ݉‚FXOҘȻRKP&e &>}Z#0I8RV+;33852֋hjcg,>6V߶A#lw %zx!XNHi}YT`CroaႺ:AP>&j^Z`A&%%ܹs C @O8@v}l=¯VY͂f{0ut4K#[ѹcW#-}g P@y#52Vq64{@}iv<|: gʄ榭GBo_3Z^G|CkS=*ՆZ:np#lg;#Ͻt`smx9yc;s6w?b]A]puOLO^0QK4@wʑOkΖ#:~.w'B^xcC~ ׺/ٙ7]f}pH/3UmQw|᏾New Am x22XOW{LaH+ L炨:!y'Qyt0~`Ǘ6$> %;vjݷV}>HHX>9bi})@ŽO'z[L@vyV͸1: +~@7 B08pZ7oR /}dw:j*Ԭ4V3Կt+y)FNp#j]ᏽ? ?4$a{q+l:k9-?YcNX^~i#_bZFˆ XjqFk=Zߴ ZКw}Tަ&}Ew=hB3̂ 4j5kh}Z wikU/+6HUk6+j!f6dm}G:?/NU,w=6>>\)@$|jO\LǬ?WW,ڊM$$\U&WSC~Cz>KHݿ=:/xZZPOG۳$$\גJS)>@@5/hH?AoWZ-y튇n$$ wn$$|v_iSm;n$$}4-HHaDʻPWon{ݎ$$oiSU?|($|4;8 ($gh|yj9+xElU Sv[`@Ucx-@@K)٠WK'=["@@@vXbUpEhJ@.сj"+؏L%  S#66LhWp0ͣVOB]fif?®ۖ١/ gO[H? 0y ]hUZ'-s{rs~Yi[z\G/i9-]"KTپy+xh}Z/F'kZ^ O}lk6:H.u/YhA@@`Μya`A-^Rbi gkJ< ) SSK> )lo^4]   6?ݜiڴHH`piH O}/_$gc~Hky0  O,BeuH3Out IH3o_R\o?Wc৖m&s6?WctKʹ  )sv@ `g ,MvnGM h+7Q7ɘLP5BLr^D@P]G      1s~?ADDeRPĊ2 .{Pd,ZA@+2z `7-  UA|>^Jw [6AFPp=0ʠ/rv:q6n[  GOgGng-h#>&|>?|>c.OEm: P[HI SfF2͌zD5PFE"@݄NFwMR+1g*     ^.WIENDB`PNG  IHDR޲IDATxcOڍ}4 :i0!^oc&n񾾓v.cbc. ,4v75w3c*0{Pi lځ**0x 0`Ї,#]qyg׎h:Uy"eīq/_ƭ!U30B{ƳW3Zo%I{/.e *|:IڟG_R鍧 ^?' /_lx\wQ3 EF.q ͤj/qUuh~VV_]+cE Xȧ :E<0 we]t,0Ӂ>uP%vȬqp ;F$9" d,x_sƳ븫 geB |2IENDB`PNG  IHDRrP6DIDATxcZr1T'! d@p(5 yF #*F5˳ ü@ z2q`CIENDB`PNG  IHDR;֕JDIDAT(cZ0H'0DԌj pLfbgdsf/zQ.IENDB`PNG  IHDR szzIDATx^ŗ=kSQ)5uARt5S5t|VEAA'!uI6 _!<!7,^ ZiȫXAd̏}.G,_mjZ),+*tcYR$RY1 7'8wsV]DzphL fe0|멝:NT *ߧ@*=Ͼ Ée(3GPqٗʽ7LRMa7w 0v?ˤsk5z3TB['ڈ0 ŁE(ᘪWil3*oP2d8C#0ˋ'¦c(葦"q`xq媈@:w[J H#E^Kc!˥gc s- %&LY!䣭%Mv+ flj?WX.(-)EX& ?X,qwCԁiւ}?m^ L V&S|$THrM)%ܥ ƚS'ɽX{7c36>@l_ 21񺢰.bHم3ţ$IZtKˑf={ 4^Z[X#jXXfZSB0v.4$e4fT6W`U؝ iޱM lsg̋kG Мԝ7IT@WIjDA >l9r+0oYY:Μffkj PNn, !4NfdbЇ{d,hcV-g NS2odR2 F@uof {;^ "R0, o|o100ƙG<$HccS,GQ ;`Bj¯md6A Sl hWaGN '`.Fo#þ $F1y_s[.En": KwV88xxk =\D7ĘcX9t33Y6f(3'd:ۄCp MF=it\wGJ'jv}_.tRI " (o[qx*y 9 Tj%Mf,1s[H]m|  eiulj&#w\.T*4)dų-~ ?4#CnlFIJpt3v^kCTi~ ?(g-B bBJ#j׹N^\> C =&vDJ4`#bBfCxss/Ct obr>La`$uX=]X\P~d(\ T}g'lߎ HCW-OvSC v1iS֐Kne lGPC vp73"`'t/<6ydYQ>l+u^DQfת^gI n'Q49|JWw8ݦ:߻8Y?D\8%^= /wb>Up7zyS#n+ 1+FLqzV6/nx_xvH_5뵼DIENDB`PNG  IHDR mIDATx\{lfg绳`R -(($´QUhݪR+\J [UhJ`&mj>mp҄ ' >Lg׳z;?ynvgw7]#B P/wWka uYB@nLw/8dYt]O|z2E:MMOܳtݡ ~/w{NzT%Βw2OfƂEZ€n}|ƥ_ŴbvNpW^+d$iϊ +m'7SEAnv8$[ ru bH3)a1!9 $Pog*e5T㗿+WzȋwG(9QcSh $# |EGb;`Ym> F':dE?%Ɍq KI,I;:pG/]^ZSTͬJ4RF<fk"~J=팉_{߼QVUU6dd T`ƯҞF!Ӆ@r6>pCד-GքjؒX@lycMiy,47U.yGifK ҜWyQrζ%]p9a;c'e4KcG\jcQ>c}3eOW֝o$UdR^Vl]=Maf QvOtkJUES%p01h];&wFGVoi#&:"KV Y]X0bwمDz;<Țd_E9 Oa67y4NVFS;&Gȑbl#Ycm.baӳS+TA5 cYDG\#LȊg}U*>ZEY-p}3wp].[#V'&>trjƽyl-iCOεdEPWCPW0[\,:N K#(QEYy#}7|i7 (Fmn7PD[ˁB6JwZ|PT W`hsbf 牓K;Dz#ʼnKVʺ߸]N_w/aG4غ.g )|j؃$)IW h?'V|A{d3SZy֟}s,U̓Rd)g*fd a& ^kמ@I `UӍAEx"* 2bٗ꿟{ r'06`]?/Q ӴDex勱'(a.-5+eZ πX?1&v VZgғbWCӡ%Ee tخ w &~OYmϩT\5%꺦TTCTQ&\-pX^xW^I$YFֻ*TU[d!+v`~E^̟M,2ƶoTEmе9A}+'_ =fYnYU@`> c;IENDB`PNG  IHDRa! IDATxYiU>eެYab,X+$MHX1Ulb?V,&h*S1FME b :AFafr߻K;玗 U>9[7)'TUQB6d滞sϣjE$R' SHu!UB*\p"_RR+IS@;G.ݝݟZsݾ~mhTMA CQ<ʐ7`гi2"Tl߽wYV1 w`WO;LqdzA5^H&j}4\.X= 11$ q͆샕SE$>H qH/iPvHDc1 rl{ ?x>N=(JR WIG%"cghvϔMi::95.^n>g0 $*ܳEҸ/z7`wV#;n2&N!I%2jx,fjژ:|ftѳGtN}Hy0O; QIdG7$۶]Y4ozu}5UWH|ƢuT;(BeQ!Ap2MPZ^EZғtN(d8ّGrno=tpc=xwPrH/MKw6_՝60ءU4ub;=`pL鋶vcO0R18N[I\_>āM@=|hV[[c \3cd> ~'T+T `B t֢52@5p UZ`7;^"8a-eJܷ\lf70a7ᴡ>h60q+_5y-1a&4 t^ˋw4yXf"7ۛAT4vCGOI~C#rRt= ) q.~O %c%v o COz;'<hz<^g'y͛O?KXh10KygCjM})v ^&x7+~[,}tD.ӆӦT;j$]4*ۥ$_MX+Ut>B0#$ _<7iFwdžֆ&7@,dⰰS$Thu읛 rN3w w\X)UFɂXLByGvP&UQB;h/)SQZѽP΢xF*x>myﳠ]օ2HUy1iiD_c!QمsV5yg޾j(%#O6tA(:NG  jd7ɂN>Aet… -H!4 ƆG A ]z_B:۾AQ.-l-3\l4Q^EiLATA? e{_PGZRP!;!i'`KWK9Ã,b"]סp֢`!i. kBU, X3=mV(0R*N+6?w N-wp fA$ź|3lf0/p?Ǘ)jaXBGlOh{aAO Z>R 8uY+n D$w.cV#t =EuRѯK7hI$wvGQ_$ՙO~qy8|j@R=(>{p6(N͡ڠRIv6CbTSOGuo m۞gu1`؏km4[4'k}\uhҸJNy8'C17m 5[d+Y꺮K^SyEbl[av `NQOJٳ]9;&3bLrB}S4Lw-: <]#Y 0'OIENDB`PNG  IHDR&HIDATx^LuNN$" kBELQ`V@YY̍?jqA/nb!Qx"y!rsR8|}`{=xlؠp2?(<\dC(zgwr[*9YiE3 euن';>8T"M9LJ́aL2&⮑ۣpO%É(JrO@GmMRP #Cb:WW(a5b3rt[p.!)0DrY62{ hpeB)/˦Iy~ _MY8X=};B|"ssE|2U1 *X.4AִPJps/+>U})[H. g[: a (ks7 u-z(w ǡjOjPǖגe"qXt_.+U$KRRK79鬘zpUP3K C#cەSNQƺT 'eM9#<ĄcJ53C1ʙ~|?^5&\RlqQ/nԡrFV͝=𦤰V! k[&^99[ISnT@T[GPh9G氖1_gאR/pCXHݲ 7AUtBŽs(,DlyxIQIףse4'ĹVDnAĝ킏nJ7Uxv٦}ezXYW=rK7Jb( dbG_|Օ9l\ _+p bgenA\/(xbq [;.u̽` jFK\f!rק_cmlohiHo4[8rZ RY[ͯurH_uu,u1eD馺~iDs Jv%uݸYS3Iqy֑Yl\^!v.]^d$3~yF8r~%- ZZJDAIH8ǯ;ޙL G35W?ﻟCxQ)R@ (Ҫ={aa LڅB`=9z61L29ҞC:6%Ւi.MϏ[村羚8 ^^H3CO;3MMhC0anaj񑱹ѫ7>tBX,pTХ$;;u- +A1UGKRmL?Ao9[]$ N[GZZ4l<KB-rA]0p-0ATQ=~9-_<4*R֓Vm:*f (Yr@cF$m%d:ێ]gcٍ]t"*چ$&S i.,86,SW.Ҵm+EXns4 ZD BP34$b2vL}a0"健F*ꂪ, .?4]Z jWHTJ(BR"ΨBYJEihjf*bmw kш뺦*dۘ fVԸ?*DpH`Ҡq8qT\A̹P kkJ9U'gVHLKffS 4u-#P*V0~75L+-/-ΰ?Y4G^RA%ƙeYfqjҹP'zn9pc yT-<{3I s/-eiKatj^x8K; `BH@XΗjn1Ę4RQ 2 W:ƅTWh)ܽ:|m6T]bޗ*!hUu72hͪPJktbu c^чhZ$Lk 'C5yhĤ;n]s6ߎD4nZ58 W"a 㩤RꂕK-8y7uz Z)BŻFx.Ckw>S.4W~DC).|bnM F"3z=$`H%1y\˵>=4> VIENDB`PNG  IHDR&HuIDATxo\W9{fl$NjI[J B]' XvCl`UԤR£!MH8ɸ9uwPٓOivw~#{BBQޟOȐf3l6~db# _9!+v~܂ $mun;W/Fo\ # fbJy[8܏}hRV(a/lwM^߹w+?}V \bR>'*Ӛ@8 ;:nk?|?H [^"h? @~bɕ"~YRNTAO̟eٵ.Wc? @5<*bޥAz { I ~*JOUNr̟g;xP.> %P p`o/~Kr;*IENDB`PNG  IHDR&HwIDATxMocW{smvdI: - t`A  ;6؂ZT*T 0|$Ibھd~W=y_KǢ|RdCt`(H"x2͐d7L2 $qO__F I-nn^FNwXCq 翽o™jmhJXÊRln~wגzl@&-Ps_}OWsX A9 }6n/7_q*Q+(g/?;}3hfthGXjSufYV.Ϻ{[@pa4Tuj4w >( *`ձlrP ʃ)P?cYyblye,Pl<^8Sc/i?VAM{;,ss_"`rbBܥce|~XNDQ(U P~bav[ťQ)я=0}``"0+ *Щ$L^𩦀d"[ SfmQ8H d'Ctp@A^ÿvoMJXb$*2b1#=[k +FrNŠ%I8O)kjg9I14VQޠK3@%= UjΚvꀏ#<|7㱘T1[ p(yWz=[PLﶺ|pJCr<rW@ ?avOJj{A xe wS#P`۷:okd1d|u'2(G.8ECo- sUin7_kpBP¨rJ@P0Uz@ڀ~_;YPF$XB[o__xLn\|FiF9`ڝ]"R A (`b}uO}Z*IF<!da#"^`~µ|i,,GL #PJT~?y!nY;@\vYL#)10)[/mȀIo% ]` ةխK ^#@c}VC'^ݚtM@ar6mXpuaC/O5>սJ\`@+=ήORr' P 'B@u/rl~HyO^_ξ쑑tMw֥ܺ4 eX. @kЀ%ax Jbx˳ 57G @qA+;f|yry,C1$4,]JRifLg&GtƳ@+> Bq7ߚH ܶuHOkih0e-حR.6_R6A !$E pVNZ e^jB{ ?qɤc R)M+1cl*$%B0L/f+D"4ÑM30 uN_Uq tlil)!l_Z0F ǗZ'3]7Za B͗e ,4/M JSJ 5j%_޷}0Q\E/^ (M +9rlJLW^Ϫ_PU2'@h:(vGр@OgK(L%^,~q&W@8`'@E0"zY@KɥTIkJ_ĊOL'JO CIOҒu4 ha/q'֢<῎\8s2yX3Hs‘fk_O|gA}2P))f <[I f:B@u\?ۇn}?{nwf) &Z;:=`hje 9 0=[I7&rRt2JMP8:*e8.OOf}M f qj8͛׵B5h @f+GRvDU_gjcq 30@EIeumfF;[+W%[;a4HMc͛vvx(!> l 9^@Mģ6=;o>>TpMC"^ J}ԾB/.G c IENDB`PNG  IHDR&HIDATx^]\W{cgfggg'$0)B mRi+ZmA}4/ЈA (XK bl_Mltnv&;3H[ m?s_9Z˃":c;H@jl9bv++|YU Hcp/}ןxW̓?9sS޵K;BU&^*eJ_H(,?04"Wt;xhlt1O?{N=Ge7F->R呝:y;@r+:=%DH!ͺds=ǘ?m+:$%lضAk`;BH 탒Oi 9bQ9-BVx` ` z`8*1_BI"m@.B9# Ȥ~2ij Q`u2UJDtP|eb$ RXtRt`Bjs~I&JYecAC rFv] Lb0 EbBB;BW$,`=lX^胀B@\ es#*fW+.+nއoU=I.Llj.ߥhZ0X""j+v?l>` []0ڀ Db:B!\[wE$2wnL!ܴbyʸ#`ej5@hDW kKg߼z>,h1T+92 -XAJ* 66i1 xv _#c kޘ (HG|Gb>`O 'L_!KyA2]1!,r?@s~~q׿}[/KQd2|?~h2*M![*'Y xdFJLdQH\PN֚P|Y[`8L@k#١|sP@bwi2|lhk@HAPID҇x o::Y֠/ s0]iln^ ;28L4q2}һ=7Zh V$ !G ./\ _9wi`_,KIVwWzP)f H`q6'}gܨ⍋iO/pz`lX]IENDB`PNG  IHDR&HDIDATx^KlW3g޹7ALHg1 xH+RP!Z$@ AwYcJ)J(M$\;dy#E\7nFgwk-\N }xT Vv˼Xo@;@##oN~Wy~~3l䡳ߟ;קᑙ@xguQRىJeGz  /a{6IW78mv~tvP^ml@a-8VqЋAiI Xp`v9Z}Dk,`֒Co/3cڠ <jЮ Rkr^|Kd2TH m:8, z`щHKlV])4PZ4UH K*K@ ̌>FKHP)X$zs{3K0 ؞JzRaEJ$h'&&YuҴm'cw Lh80Ѓ_ ڂ֤67690eW^xkS{p1\ש}=d洛w =: k mP,A` ƍ1˭7;Wɓ9 _:8I2 6xm5ٟ@o9󙕫O`Nܩg:o.Jk D$+h\:!߬CٓLEk/ ˀ'v)fXVtFr% IZ0 ̋\y",  ,|\RJ`2엾 s=ؽSF;H23Uo֐*ףX "|P:{9Wܧ'~ (}n!W||!zA(N!ՠ  xo\WWʕ/w>_h=HP.I8|קT PzqďKSW~HvZOWOIENDB`PNG  IHDR&HVIDATx^KlWIya(- EUـ6t ,T,"u<(В$D7{̙s~,yf(O:ѧ?<-%=,`gfI|q“Ȋ>P|Ls7 S2Y@␕u6íUzN:{{@OXڋF/}b?=R!Cu)Uۭtw?nQj}a~?=ڤ9 TP zT*4]%ߜ'\M6{嗽W$yrkG^:_gvoKV}о Wwkhr55G85]/~l;@N)bg/}l]oHX0qasIqRWF'b٢,1 O05 :!1 -wϩ2̱s5=8 V,L b,{pnVS@$_#CM=n+skIUz5nޢ-*4Oۉ_{ۭboev]o?2'( +w "{22ԃWp N x‚{Pbpo۹`*h./ 񀆈+CkE?6Qג(T *8U<ĘP$ID'e9r@^F<#zc}z]x:ZFC[ T"dRRXR`?ޝY?d#uJOmuGT-wqOW[?$(r_nnΛΓ#R?ƠÈ("*RupFж7>3e]HExro{ȸH(޺[7ޒ,=J MgT[rC(qZo7gǦ*~_?3 Mn֑t{~b`h`ǠQ!Mq$9  9ܱw~؝<>&l}Z*G/P* 9Vg+)R;AdC@]>xirЈ`A;&뚋sغ)'*L90YQv`AD XiyHؔ7wd; aG\օ!ij)tWj4zV?5`CD&} 1KBY#ۯۋ4eP{7[1Y+sUݗ&1 @MՖp*`ǵaAy>/$qYFT)f!l_$]%. @4OZ./E\k"WQҁVCE4G}.x2vN_ቹJpȧ29МeB@ A&1YA{d,2s nS$=6tdŠjr|<2ɡS<>,0ڀS}{S)@Q:1i %ޛD=σ8]G6ߘG^でa9=cP_<+5FK̀GT`pծ,kszhyLt|{W$'/SmŹe !w.L˧x J\Aـrmt@GN†aOR*K!DƢm\spח.CJE&eG՚G3M!cώ,7&5Y#񑤢yAH"oT'](&N5= ]\z)f8i O 岷 g<pB&t BC4?8WxƏn)vkdR&I/C.UYde*Ei!JI/e i!Pbu zeMDQ"E!,+j%E3gfYY܉q&Ncb@"BS,/,s t}?%ٔ $ QY&paΜRaS6aBaZJ ZҸ;f7;6>,#[=9-MN3ЊYw"Lx{MTޑych1saL]{fXזnRU!7sua뾶C;@R=w<7>ߞ*7PJ@#IPr{%%V&J4sHmʤ1M1dp"Nk`T'i4 r_t+݃n ] ]cv2h1|v^}X嶭@[Rtw}QaL'%RSwyzfCgjFe"CIENDB`PNG  IHDR&HjIDATx^i]ggs]ξ3J IJK&(EVBR$(JiRiQMZc4iNd}M{Z!{x?ye_|?(H T*dzsEQVx hl_E"T*Qߟ,?{;6ٶ]tL\~ xo[ٛL&_uK# vf2u8wK-F(:E<®[oF? iZ* l=<.5܌Q3xG@k@՛ 8T=W>uPn[7/! t#Su\VBzDJF3n5kU@#-5|טH$~Pe!M_gVj$cs2+&FuuPD۲( ;ڂPGC,QR1i\AKBe,]a:S#_qЌ(ZK$5CSz`EZ00em;!#f6*랾0 #RP$t˳f=[K5Dɥ /ŚJoB>_MrYU=`$/\Xt|bCQ <85/cu%<шN%I +P: -8?`DP\E?ڻ`ZyĔeXrN)TͫHCldu<\)֢:+O|QR.\ax~++'}_߇*e;y F)_=;)npDmM摵mʖD[Bcy~K@``$/o`7mj1ߟE#6]I'`,H"oo}L֝ϹS*PYci\$c%&-a䌆Id_kx-0`e_hԵx"LZ[1Pr<ˆL5\θJ4bQTkZfQ:vv"3_Gf>M)3M̓3Kz( jR(6"2鑳SJaC΁Mwn̦T6$Yj̍&{ FLmg T qrc[L(pF:h\XKH,Ncf C&T6 Qg_=ŋ%WܼQ=0_nhKᑽG.#Ȓ -iɔi }ɧyxxgAV 0_"I$U@ueLPHEj`h [w׎[?w <Tn ,[͗SSy"r@F$YFC6[bՊvr3S=~c7}\,r?PZVrdNo O$ YC*_'Tɺl7y/@]ݬ2cJ&G/7깍p=opAYdf: ܵcm]SN\itz)5d v'~ {[DIbV-wGѴ q-ApE(ۅ5dp贍޼y][;]' :>IENDB`PNG  IHDR&HIDATx^{pTƿsc7lvd b( m+J}U)# uF3uJ}utt3+j+JP II{_ΝP͙ɝ;pq.!"_x\ \Od!*WF)Eà;\vx`?029Db,̬~Yŗ&saX<7eo&3cOO\hRee=͑mAʟ J| % (Krwګ;h P`U / @yk= .`xt&0m$KQ S ݟ+uh Muͷ^~waͦظ6yR 0#Q@4T)2a"XʀȠ,ظ%[_#d$Ȕ|aP)ܫS:*{Gw!Y=<!^۹#,G_G0qZ* K8vNXVrVD={ॗ^G3x0>aSO,':98cE|pb [ ,̊^, ޞ+JPv??6#0怹.yi6 lz=l!uh  Q/@!(6#'Ih H)L +E̱,+WOnm,id qyrxqs/Y0a iç*şrh9"ABڰ\uJ=iRa4n]>[nZ7]8L˅]%!)/09P  9tȑ<*](ՓƉbth FZT4ROrF *K(|;N( > 2`@|(10n{ 0rcYk4M=޿IHPT*?Kf7gƫDh*D@SY'z _W+Ʋp_9]KQߢ*~:B`dtLfu<8~`x"SbsƋb0! l.r6xGѽ&߾ f/ʻHMK+"%@R06-y_ !wQOdӿmýi]r'w:f5qzA?EBIȘOPxxR_S!M>K]R_uEՕ"7X!X+ya|yӆطk&rYv𪙕%d[vDk c &|*P̫Ȃ㸬@+ }V:6z @F0]cC #`ܯ&F3uK"PUo3 4sNYa%緿Z[H)\@Z KCרIF"s-HTQØf0s(-ekMR@,1ۀ?X/8q=sj0gt(MہƇs{/M"%}MXoRR|T]0QmqO{1sG1̐J9E 4M'we@|(p`gZT4KHHH4irm㦱mds9ҏeKəb[EgKZGaIڱH]/4„blbBJIHс+D ?LDJVrϖu8Id3]fiB30u +u0fŒ`$T/Ru \!$cYPP$2! CꭀB˓za|c2tK /%Br-:jJP.dwo_ޝ}l6mn\6.cp^R^1Ճױɺ:LPBғuqLs _ @7$u  $LB6%R\SǔMŷJ( jx?$Յ&@992܁P9+['.4Z0=:-ɦ%zF۶L!8V.ZXZ:q+luLp/'K (A E(g榮TLj_ZhX[DjmT$AZn& 9ToK:r)cu9DZ4k % ԡݖ}yFXNS}`v,޾ `hdphӎ_je !n>h,.]+~g͜s]cUPN۴M8yBcL!u7]=)͡pIENDB`PNG  IHDR&H IDATx^I\Ww\n;$FaCPDdD,سCX VAblE2H!qrm8Po_WWOMJ>үzWW9qRxа0Zj>!PM9Fy^[G(i5jh{d@ŵ fg`ޅ,XJÃ(Ϗ8ѳD{-k"K!0AP9X}9 j W).CDqZL$0$(sMmZ1 :}|rwLog u05 ӎHÂk{̡|j½!ۯcVMQVJtK%:,yȉ} aZ1o<>p֮ ޹]+QE $fv Y:+uRY_+A`P=fӉjdi^]qRv?*nvVv|J(@w4c[8PJrq!|@AJ\8Ғ_=bI s`YddC:.,}Fe M|`ʶ!Y]WtGSJ"M.~˧!Ob{h[ VmPSRґ.*ݹ&y/{ؾyb>6\H(ႡXҀM&@9o/GϷCni|ܶ%"֯bDdz!o%dȸvL'䕊бxn~g\C'pMU2tmo+ ly\wF ۅCT 70u&PB)Jn_dZdwlϟ%~BXĴ U7Y X죲,>s(7r8UTҙ7*k5#`.TS e |v9w0L. BQyxIۅYN*DY[ 9+$سan!gf|T (U$Qi> SV1E>Uumt 'ԝ[^rN9f,L&18_: n!OUV˿tommLFxL_sl`VO*]t9@ uӕRT :sLk}}/*ctf fH\8a20TBiِYNyto1 [~=e:'@gtCUt4._1F0='g*$tl@TNh=4:N_Ie{1*/"h0R@4e@h46ac83ƵqBH  %SNec`4)s9NľG,m8)B8S8~<׬U[H-IENDB`PNG  IHDR&HIDATx^ PU?ჽwAD4@X"fx/J*%QBSD/SHi$ESve%n!`$ >yg }3f99cpC,",#H^^^|E852=DvtCGğ,45ZuXjfyI - 8Ӗd"Tncg*=L&ŸÃN8$;#=&)EJb3ꈃǿ2TVBww2!C0hyi_BES!{JGFɐ?6;? ߸HrY 6/[~(;"Ő}#n btZ,x˞F" f@l|٣2%"ro&45P:;;OT[577,?6fZiG `0@KK tuuA__6صQ1-bT7iڬg/Mer18[v&^F)GĚ%"hn~ǔHb H{ֽ$\61+dYrZ:4cR]]$1,3zP ۍnݾ[)!Zl|QR52Q"uKlsiuD ǜc{Aw Tj}qHJ:+ V"֋[w%h1.16,H< > k yrhWE_ BEGKXGGX-&#bbq ͆ 1-_$bO+gR "1``zA(a7=qc1>/\.2-ҩ+#Np vw/HRZp`}I10s)5+ƥ ~}·y \ /("]J/TIi3Pb p8\aaaD S&M%P5 KƓ0l2 \!{&rB,=J5R8g0e^8i R Qkmm-!gP"BF5}Sv&%~D5BJˉP ZBVa(1J'8A& ^>A'eWUUb"j"R(Ƀ/ͻZXKPb)&bcqF#rWɆ|.['N}k?DlvMUz>#\&|3wAxչ~2k}b:| O3g='p"`+K3 @"o!ZtE(2e9bLJ'dlWtJU魍qyHbfʙ+P(GDƤgɕtڨɱƈ'؃iTrkUIENDB`PNG  IHDR&HIDATxs۾oWUw gLc6m۶m۶c[ {Uzg,}>N#E$K^Q.?_lӦў~]; ^;4ؿ9MŠV:V}G=GGTmY/]I&'ݻvj55=#z3gN='_z:KrCd/y5W}cm5[J*J@ )yNٻn1P`mkn]ӟkKYG$p&)ׅ''t_-b_Z}M736IrI^'Γ\g,ijOʐGE",S|~?4}݆6^c+obaKZ^ ^ uYLѭ293Ϝ?|y9t_X> :'4<ͼ ?l+y@DJlKyQb)\uooEr-6y_z7h%5[n_?N~7I{iE 䡣}opg1kOq,A7q'&FWcztc߿?<|yM<~/'pW}XQy5>{{vo|bW;~~u7`:y|XJNaJ\ s?s|'|uTS}[֮GZgdbت.yu6TM\!SKaK#MSk{l6!NGzKF` mQ_Z‘HFU*EѦ&H"sg.koOƹ1RI#DZXVY3n]^N>OnI !QL7P3DtF#a(%eZ^&/pE:9ID F7P(K :mʒ-#eĜCqQ|( `@S]brļ Bd(."1^Kx mNʈx|焢pmx={f|U4bK8pb$J`]Ͼ>ZXoM=gN"D,9ߣ.ڢ,9g7ED=7zxՙcU4`i1EPCT d-elxDgٝxz^Ѳq}0.&6JZ#B0.BVJE}ѩf9ѤYx||ϟُ6冤.?3ѪstD_L`JjL/ 2Fou*;Ny&JVSabM'_~r:EsϾ~Օw!weߗ*(D:ƾ]}vVLziĒ6HS,-;)̧~hq35ћWDKT ]eض5\%`f^SF_հ ~)\@2QǪvջƿw:yϵD`ZQ.@m>/559+oNf/&?OpNb~IC^PVo]ٻO3Wכz$:'Xk܉B,KTb7\RP|`68qo F_kzuyr Ae'sO?tyqhRTX|X@W䈖[_IENDB`PNG  IHDR&HhIDATx^yT_6Y!@d]})5 wL*L\(юB"j 8 r]RAEkFA. 819s31߳AA@(3JHCeBA?oyC~9=sK\!T"T<0/=m\rJ){ {܊tձ.ފO#H@|kJSքcIˑ=ŔS|lOZӺ/`_樠sPu4S9.&з=fy[JOQ}XI+z;EooVD/62Pu5DR7.d2h1YOMd^\f~*i]JTɨ?!Aww7dCmy42'ԦMvPҞvS(;[p x* AEͫ%! BM6 ?胒'O00nT6sR_ʷ0i9:;a`E.W;' =23Z>܅T iFQv==4]]!q ȢiQisq .q Le4fq_'|k$IyT'fgCbEx\SbL^#)8S Il?RͼacZ g.Tun=D(4WFwFW|͋5!nG $iIb;QwPj3B4P?D7 bb Kf~,-'ůO%ݴ!f2z1ݱ4zzP%هٸr){ek;D #.J< qX:gjǶ\tP TdcxtttA۶᳏Wz/(pe4tpjjj|G>+caIx!#d$3pz鑊&"afP:Réy[b9Id kfKģRp' g&x D?{Ѽ~E=J"<$A6IJ{b \n1tCε}*qȏ1]ϳRQރT丈1 ZUh9_kejD&.| i/tXY '*O"9S ټؐ!44>\6sʉג !+H6'B뢦X6b( FO$0fk8lqNv|y*&Z3wKQ’ٗǺ8'iw)=aa2_ūKP7s3u5 TqOgKIX?hG|^v~pc <g,[] L6-DhB0Cb8ԗ鑘;33F]WG/ϑ<O=0&uy"3rPB]rY/^R'kBD=g_FD-L5tEqs8\fKf v{8ךiBR1[3el\^Wc'6 dL@X Q-zЭa!LNv)k1T,}t'Դ 35[@kY@ kQl$vmg`yD>q8B2 {5Pv+{J3xȕe**UjԄN'ArCױeYCB[d"g0b ̓ca0>VA$`$K%w>,G.tHIENDB`PNG  IHDR&HIDATx^y4 oQJ2-W,مTҊiOi zE{IcZ oc2M!0uv*wqs9s;>|7Տϼ2 #"cx/cZru ]]默BA gsn='d 9R b*gq䚯€<|؎3q.? Fh"TIo42{u1^J%fn@\}$zY^rC4f^&!ߛHo6rYv(}(AODA"T&o(r񖟅>_|=&0YZߤVTdZr#:/ BQ<Ԥ?OΣ6 o;* ͵WPڌ=~}|A꩏Wa,|f8$n*}rn4\ %x'~w-x%$T*jNm> d m$\DRFSK2B7m3F")yim@%%%s+&m ytCa@sU<:__#\WV@8~@LG?b}WXj%,$r҈Cw9Li)t>T]P͕q=khum XgSƗS ƔZ0|vakI>FۡD #4 KYYYVz1[} v/s *9lsb F$km%TsY{t\6<l6{X+@K].;pޤ1>}I0xi)Zژ1;gpqdCQugx5m[b墲LMr*J .qd H衛hh+=ɔ18;O$#r#@Bww7^bh57@  MH jMT*5}'S,ɌêD|q c m6LSq#*9BKK@2elikGZ+A6b)c7g&Aؾk~ Ɖ'xX'⤲aXQ;57Y +ף&qgHKLjY;i>ꇸaaZT?BSSJ%A%O!h_W}}Bh5mlDJ#G ccx̞5r(#>>/woyk+҂NVtLQSD{k/#]tТVՈ8uɘ)cKaDEƍxΝ:9 UR)dRjf4R.f7] Ɲ; iJvht7o!22vmX&rϘ1Q"¨3q+W,c◼|孔VP(&ƢGRfxFdSؽﰴ31Z@NPț~Ӝjdee#5DGF!pm)s8KseύGճ5im#?DAi)D*EEM-KD[.l0%"8Lb,1sXuZd!ǥim͵/5mP>ku7Ɏ]pt8%27c 㼍^5B㈩"#ɞOzs\(vwmg=re@8V=^%Xɉ$b*1p" &bPL۸8J7RIENDB`PNG  IHDR&H !IDATx͘kyefΜ^YEڛVF+D ʼnKiI~JB~)iIJq&عUr\%,K+i\;oeKEO};y# @*4`@ =k/Ա}a䱉SeW+ǽĭN7 ]ԶjhSxK`AI<<;SOό"!RȌ-+u:N.V57kWtW\fR(x_~_y_P 06k !ʓ-B_*b`Wklܼ߼|rmW:^YB I &ϙ߼чxzVѣ&! hTkLP`, 7)agޏz,GϽ_}o  '~W%u6Zǐ3R.24c"VA8)zVcP9#1W~z3@ ԽRcakKQ(ql + w/!'_8 Y,Q#wCq:(SwpE:;G;k& #ўC9(|C; Z JDEQ>v Hs,ך(o(V%>@d<. |GS#[B_ c&4cDZ ]$<\{yxK5[ U͊K?2q_CL+/T.9M6EGе6z!;fR,\'vy}c܅ w 1O-<+P}{ D|r % NCh$2{ +H<]ødfRL |W. i;2<~d2mvD63s,Cp4LTu )8#v4}N?ې*MOtf.Y7}gך mN44BX@^XEͲ+KXwȞf89A($&2wͮL ޤϹ/}Y=6{|3rڙI.QN K>4ihIkYߴZsQadh 0F&a J$ ]p&$cl(9P@DT|l0oTg.|{R Ղ6Wvd.CBw2U ,+Z nDg`H6b\e<ỄaFtt[ѥh<+NZ 1=7<3XTy ?ֹ͠aA(\RHAƗxZFD)-Y-Ⱥ#Ca Ao^j @ =cQ{Y<:tԪ"a>ۧw3r:+UD1pK>fb{/tDImq (d%’9#_Xŭ iHɩ,>l5e 7O 4_?; v^o:a` HEA" ~A{_UIFuub?6Rβr12݅w; s [89Q^٥SJ>CRe뻗g /Z.PzBᰟSd%Dbl`$U h*d*}ѓQ !P;B[*!^Lm߻+ko">@h==2_\~a8B`8Hb!RdlX,(i6:4VHNCqboTk]n4Q`]8}RԱiT^fEAIx H!!Pp2 Bk|?ˁCGZM̟3pw- ld" ②L ҁ\fTtg坱|AyWl^ -B ll=|ńzxg/- 4=c:Bz4+)dݑa+zÞ.3\zCcScV DnhM׋{ʵjFs5u1/9ivg/$ ,lkqz-B4`{N@4ǩBq_ 9Y0g!k ːs,Cf 6rIumʌ&m|0|/A|0 (aNXx#{ΏQ6'fue~ς pz⨺ǀ(Y0L (1 >%a[ 5<2x>j "Ld.:MP(azل7,ؽ CRP; K1 shVG,8^R@҃2`^s ` ,XB}(0AUAe&t:AUS93TqϠ",YĔ$؀id W?.()ʱRRĀ =6Ά}YcH?CO,y! T{pp^#㠉6?_9v3LD\gtʊ K*v%$LX`ʪH{ `5"&[HӋUcT`~EGd}bE> a ycp/N]jAvsϱS1fkpp%Qn ׂd_<>Ro|"auv~[I`FTy-!VU#4 T/O#j }uIENDB`PNG  IHDR&HIDATx^ŗ Pg\Q@PJ@TՀ(W Tu7u=7+`8xx(K>f`fxMMWQ;PVeꩿ{ =~hIt?14Dԟ `l٫fy/7==tb;E%:&& Hdb3h!S 58uًƚ`v Ck ӍjWt1'VC>4bɸEC>t8KvGYLb=T#)}z eL̽ƚofbz]ݏj(s'r}kVвi|Bl  j`ebv{_k|y;>T; p m@#bg@3D([?m{|w•M/ŭWoRDGa@ _[2g`$bgDF8. DVHY8PmFyw.o)@b?)e( wnM~bz1p*:Z[4!g7bEƸo7|@d-[DK[j<1Vi@Q~vغSJOXW) Fw,ΨsMye)ay9hʅ<% K@KePV2gh͇2;-RH/-bJ}?v 4t?M:Y>h&mJjzR.R 70@-eټOZo _$KWJjk]) _ȟ]d ԴZRI$BSzHD)U&P65g2sJ&>2ZS PZ2DdBP6iهn.Ɛ96NULk,M= 42a wS1y%(5./yl&*Tj|?Sw +ׯVPOӸL(.%)e4IeL3_A]hg}2ќyX&ՏPk(8b/y1sX[<طRvTRz Hs;U$q } KO1iz^<; 5 GzrF#b b7g &BCA<-PKnqŁ!eU8<[4?"?-x4G!-!HݹvȀ{}cPdB1aK ܂P{$i 44EN||+! E㣫@Qh _u?Vb_)3^#VK[/O (A⇶P%]<\G_AS,ECR(93:+A*oBtKAOB(@^ k@ %%О(B(ďRcoAz sKVz Uj|ޫF 䭣%r(P-Ոd҈S?x}/$SȆt{kՌɘMWGҗZ <7iWAu⅛y.xbw;)!}@SNGK,F5rmWNp y+4O+)P+ e=RJny|򪎝^S۝Okmۇs+R)J(o:i(X- 2Lt\rD)һbWVO H 3(C@$p e)xP@,k+̯wdz< X8Z~^^ 5#"@" PzEDm.{tǕw?~~o^;?|]O|K Ą NCAbJhH|rކ^߻ň&"R @>bry?O?[cO}0=H-X=B_t㥗n|7ojiVLG8!zp?;}";\mKJ <!Fh7mhL'ݷzOƮ~A\ު(]9ַnhS H$x<2J,p +|iqxwd'g+7N_ܺ2XeD[?MD߿i/!%°YKZ.iQ Heinejn'*3u4+H N VTõ#شd*JI[Ci) ,Hx2`Ec:S͵J6 %ۿNPFJ kBx!`zx<718PvQ,hw^{mᾝ_B6 $GOjj$ o =4.wFцPUq 05! TGU9Gy~ɟ=P$@9=YnOiJIBtFHD-\ק==HaRLRKL)P (QURJk,Jd%]1*R`Z+.'*XqhJU3(ÕkIśQ2A*lRaLfQL2 SsT*e I "0?p|Ooso/gL!AyKsX杙ELKzlPS9>(MyضLz K K9fNN_f[ႋFi]1/ '?D^[KN+&fKtlI?t8˾/LxГF4In,v7nlcd(aA!J%E!0%h!/QiB=6k`ByJc3#/ b,ejϻY`.Iy/q* #H{ym.$ZBTT(aA6[´ kqXEZИ XbtU`1p}:g~hg{K]fǧq*nFs*lT 1dˬ"+]'w=;Jcp5{cW_+(4h.lkStMҞ;< ɦؾ}kύ6N9=/őޘ3b9MۚLU-)X{ h_lMW\rƪd8qg\GP@)6$hj# u픀5J)" az{hlNRqģεg&&C}ٯ庯JMKg;g=M[g&@ӽ35%J *b]JH}w}ƋJEgTgz <]3h!hPkP <Sm/YZ;*S%is! E. ȀOV0 `is =?ݻ~ﱉ­2fltIENDB`PNG  IHDR&H[IDATx^[%Wk]StO方dB2@>qbtF%E#(1'胈K`QDDAD^" B$3q$Ngھs&safȢ.(jY KT+-@;_kx?mC@,"v.wMj|gՍ_|߫ nͺˬU'Ns&3:WUՊ%" hHT@RjJ$,kx-,#[+ߞ! ZxGa5 kkk;1{o yQVHO"ņu(8h9PԓȎl.M$ɦƛ-i|,K\;M+/=[K{H8؄f-WXıp|{s䖱!EYQYk@ +1eBD2v3?'pxFcyXstzD΂v3 s]K(^.UUEs%7O)b G'9kpfK=^^x OxI ֎Y`=w&?3 }ZdP@ $%<>rZ@"P2x P+OCbiwY`[>0|׶,=-(( mzūK=9?dSbT@` ((}`<+өo^'"3z<:'_11 A0b֐ cPvԘcPy^:&2(-3.iDޮ3sj4]tߝʣRe]+%6B=31&18/-z2#+=A޻;|V];5ӈ=ZV:ҳ)Vh0`jF(UIbvAY*ybP"gf_ @&1tg5hnEd3TRcG=5F~Ő:ClU%2° "Pu>$[uf&t;pD vF#̰G(Qu( (,@fP0Ә؞t iDmu$ @*ce ZB,qdPcaIHR)[ξ ZJGY􎎫qzܢ幅VGpwuq}H F!+P-( r4/̕N?]DIyz.Z˳aoFtO_@=3e3T -=f _%:}XtVY*Bk)>b@m]ģ?,A^( YAQ^v  {ȿX4BUʊ)ylZ䱿>ZTFY"'h0DxԵ#(A/6Z+Ptϴ}Ccq"6M8 A)݇.Z'֌;+#¦6a3Zz$-D_UU[_o58KDĹQd~# `ֲ93@P"2ZbUU@_x7IENDB`PNG  IHDR&HIDATx^kPT\7Q@A1`,h5aR  Fz명*(w^.Q"EEDVĊ!\D ,.aaw/>s9/s0FgW'<6z#a?O ؆%&SC؄64wlWC =Ds#yc;JQՆ??wS޷pnDi]S%[ʷ쯁lf 3$á#(+1L|bJ_Lk^ɀ >ʁ/^ tuB>X5~}&BwgyNB'dly'Ѧ]7pJs3$z{c#> ̪̿6 9-j@9HkmSS$ ;CuE[L.Hϊ /q*~q Ld4իؑnQ݂=t)v#$ԭ], Ep!Za0 sny@[,P p٩;|e\_L WEh Tȁ-d}8#G{]l/bƱ{X_ĵ[X;ГBmRd3R^6+#)Mr Jt0 tqI4%ƽd:ucJ(sGA9Fr]ӟ\>Ctt$ j€|5g߷b-M Z`ymbNf1Gjt (5͚OO#ޞFj* òd >Lhog wqT ]bM) ';I)w ofx؇ۆPѧ_6Isb`CrOATU1"pV ** i o*=L'-'|JABIĆYwTHn[p$_%bKPԂN@8VևM5J) OO`cPsgKݟ7={+,'s%ZF6)oW}Fğ&5r1uc]C%.e !ӈ1=B#5$2F d5P*ؚbs e{(`%3 s9o=^%Ly{y mJ4*RWd++d΍!G5"HCt(z)XAĚKLFfasOߖjro.ps|0]>ڻ pfK6K0#zmX= :U@ t` 71<~sWAE h; (}bDג!sfw]:3= Jy@a +DLAp>^B拌#kRŻsjpY5-mDNeD2LLbKWc?tuߊ!<WJ3v6vs.7Z1nb"fK#j:鳭-JH:Ӫ2oXl~uDbFR7ҋ-^/yC%z[si/ܬiuȕ}bLrC>ؓā$<2ڰȅxX2IENDB`PNG  IHDR&H{IDATx^ݘ{LWAPy,mQ耕VPBAS0,fles>pEqE$KTC9| NM?ۚ/s={b!=:e< @_-Z@aĸu_uaaTԐ}t'^dUt#O`}?)?x?!~O.%VTÕr\OdiU8ԷOznw=!H_:@W coM*-Fsɋɵky[~huH\1`qZ;f.nz ӡ)2Dخ! S^\ٲ_hm@]:䦓(p]1d/i3>+F[(2AFR #im bʵNs/`EfdGX-:Hdd*XV,𨘜gA;烠l]c2L+.bnz 1":&iF"ݙCEhS#V.|w 勢TA9m3E}Sy6$*C LY鋈Un';NxЉ1=B($#`Nv\mn`r[R"Qs:Sx# 㥶ݴ<Ҥ~xcH0,DdHxϵO/?3H2˹=1uͿz c1.BxD A"h$Y)7 NJS_>2""p>"7>!RkCmch)TM mCZb$@lnɲC.:5{Ck)g^%UwCHRiNP\>wb): X@Zؖ#D”Ԧv 6_@soDL!! A~P6GT,:Ƽ?Ju%d)b>$25! GkIe9: q_,!Жj!\#m  g&n@aXR{+1C-e;H>-}t($9l>XQٖY)VTO#$oDPDFd$ӂ{*7s BB՟I^ \9~/OX?<IENDB`PNG  IHDR&HDIDATx^͖ l[>8qb'n$Mhiۚvk &i@`bPL6MЂ&MiM !j0[k!PE&8 wj) !/}::/߹>BJ']B(=;QD/=](4О넺Z7n!4Amuԯ *͗֕`J@ /6a0Rq4M`v4ަK$Kp N.CoPqf w6q.]ŏtk|nTg$!(ի@/BP]S4]v^-ZB qp]=odrSxZHF>I ;㦐(,jXHˊ_Kz++avw7'Vmcey{NRWzJT {_̓j\Fs{D]K0{PW d]KV|wmZ5\`%N>8d [{&_~Cm\hz&K~T*{.r۵ڶ GSp~0'՝%LdF",P`"2Xwƭ~+kh_wěpp@U@ڜ%Յ0Br} RJtW[tXon %X>8 _O~vegς,̕G54[ps:8p~=[wwzz|1$j82AԠUQn l_Sϼc#j9R Pw!1a8nƙ,p2n6\#1fÑӐ ^Et-x1~%,@f&|q{Ia=7W*5e/߲=L范Ol(SpxNdaGBGZ^L]Jf0aq,ʱ4dg̖F=VMmt`h $Ī.x %@Wsk4]/iĕ\߃q#}\Ar*ϔnTt*n"C$ءn)$4'`~&LH塩B}VInx<HȩL1Ǣ%UnQ=zso2M6F3(` +g]k 9z910X m;7u͏j5Ha00P  5På|O:j 4֒b:˱-Ϸwݺgbk H0@4 4DJN3,¼( Dt0D{y aP @{EZG=zIF(T6 a ji(ÝS LAC 0uLLמj2rh&iI>lPE(@Y, j ׇtƦ`( Ces t2 Yz57u-ohRj.jVA( }$yB 2< U\dy޳S1 8@g[>{AA[Ly}#SYǑe@ׅLgtclА޾/-7*nn_6 gqTXX3s9سzc U8d`eEM@U%\'529e𰢔֡Ҩ6)x?: f vg 7]m_r^kÂyf(GæH$/B*ģ5FM$tCC ʣ؎mgdoo>UlW@\5ZjPaψS^HN(«[Bmd̤2 3=ҕ\V]t  `K)vr BA_Ԋ̉}p7/h@ AW}{UQ  |lvP1@ Z*dTB0GZoFq-IENDB`PNG  IHDR&#IDATx^j@C&ADEt%b$syVZ1t㿙ǁsa>nF!emYcJ)% Za2eoQak Ga&jIK6N[Xtc]1O-#c`3|s<7AWg56+~FϴXc~lRh{ze C_XèIՓRiC?JWJDž(j107j9RJ=YV̑CXl#SFa<$1LIENDB`PNG  IHDRYIDATx^r\o!8֏U"j0$c6w3i-t ~Y՟MhBЄ&4 MhBЄ&4 Mh7h4o) hbIn8:Y5K F'M㳡ÕDw3 }ݙ($tиSYdh =ZuoU-GZc1ZwԎEnu %kp֌ftKpUjE7p}Wg MWVt#֋fGp]ݠu7ft@ntqu-`Ѫ>ӆČ%`k3Ѕ9!:0+5gsѰؤu+B"vC ٛ&Nb66Նo&~!oCfGˬefgMCMfKV}TO?EGO?GhBЄ&4 MhBh{m.hopį@t7pgA!7jzѧ5ߠ>Bg\p~4 I]PW)CWaꆕi N Z2ѩ )035e皧"FͲ[:UյvJ֟@;@1]ݼwWӸ,3"uQm٨ei4;@cZ@B>Ӄs[]xǏ6D|mAf1r7x&/Qnɶ<' )[ٵ13on[+ D72R&U8$dwD=r=!|t8>ƣ1?M@l!eo_ߞŌp(%d>-(|S#ryT/"M@E麢3aK:( AO~gΡǣ&EWxƺX*,kH@x;<F)( ޥI!u]ht9޽~qYoBQm4i$,8w~#Lgs(L-`2K@8h31] )!Dӗ >h{o| eؐRr02&1_?ڃ>&c}z!r0:,JPeYo~]>R]޹D0>cUbϟ< (/3Q"琘PXF"4!"uD J@Q>WjfL 7.P" :Ta\1o7q*ĭ<>zo^(ɿ %#9ᯇ ޾wvBGպt>C9?}O C`þCo%'Ov޾57]ҚAv G7|J.40b1\0¯߾)aZYt4:A׸/ w9F w֗4(, xq9Zƨ{<")Vu Obj,ETQQYPp樣pz/^F{}=! ʢd2B<Mݻ*\ީBj+@(J+2br2&( a FE~)~DU a^0ArG/$p19x$u#uQQeH.ۓ" MXW!/DQo$ @BǪ >_^"BLJ#fU)4d$D%! 1ُu _8%!Q;> op*1~}o;:,%\K) Pp90z\MQQL%+TABU`v1D;##8D XvܓW'eG=~;G3DH,Q!r AQ*WS D $4"xAD*@.mu(LsDA9*(WB zSuQ۷*ծCD4`*M@99I6(,D86=UDˤoWiHCc/z0BJ? ceF#Խ>^cjH'j1c(vטΗ`O |} zP_wN1F%p7ksj&aMW+م,THuRO$alzuUALj5~/}NY'Ց~6y:jV8 ӁWJ@lC||qx?}(wn9b=DwXH-˹EJG3LRN0gr|g6#s(uR@$kP?IH̜{ uWIr <ґF@պ1}ihKR#|#Ne1(-u^h,ճ! >ZN$CC#h& h}aK bqDze JryxR _z>tx5) JkO$gyis"1> mYSLi@kޘ1Q+<,sQDm?@A~"KBJ1D8aP"՝DP`ס}Zٲ&ǀv_ TcZMeJueD4ʺ}:* }=:|j7M9p8T [-@P?k,պ o\O^mETO<#$F1@ qT*zt.`ym[FuXgv7 t,atNѨ)ռZڿUIչy3A1$c<5LEҜFT1=YLpxXh)^#= kXr13QboQ ȃ|/'UxzMR#nUN X*DO!b.Ic΢գfdr V$ޡim3AS(V?$J=Lbx{Rm6" " & lefDW[/-} ayC$S[T)bw3 *4%JTwdtҘәa6Y#%ԚꚄ }\DTTO߯y 5Ճ 轪Ͼ^Q]E{J+IC ,.|rr "ѣYIQw|^ Iߘk4h@T(;L^Ol"t6|HwQ ko_|V w#ZIizF@䒇%G (u`eY#QԮrlUBϮ1/L@x5s%u~A< &qiVJ% L 0s4BZ̃6eHGhUFey0~nOZok5܏V(x596+$xZ~ $Z6umlܔkFG۶B:L1h4{Rqi.=m!Qz\mz[J~$O#='oI)r 4}!xI9n!Ĕ*k )ROG%Y~Eɉj8p?j:HQ1˯p7_j&Z5w~N3w41Q}'Z̜IҡKFq  $XL%sqc[Dy8uh~G>SEI8'O d}8) y jv#J'ntF4""jeb%ޙf0ciI@6>Nm U~l ,Gh:aDze;)!zUrJbd.dU]\#zyFͩaM\ ^<XUUb RdP Ib1wQu*v35Ft0(Y5$՝`C%WgGٕZZ,=~I@™z`%0 bR0Ljh"9>hϑB:,ˤ&ܤDb0f }|D:b2nSAʻ2S[0JԦWRС u1e׎)LƣeU{}($)יݮ ѺurW&ԆI@7wr|:p|`3q"u%A++ R;%j /sELg|uu(~NRr=m%HɋJ@džDH$WU/S8҈+{-P||~N9÷ZlőӏxABbzc7dIzl5a Pps7j]Ds6)~~r3hHI&RoSKRe7F%t{<\Q4.IIͫs82-~ěEѝ`ƺb&b=s$ؖ $&тhȴHNѪ:z2sOWBH( wT^fsAu5XZiGB [E?DVjB3ɇ;jbjKfjDT$>*ʹbkuv`puw'_! (-0j]"7}{%^IXz>Gש;y "9|ƜcIC̵}s;c}w bsYoR穒x^뽹|KŲYmw;L@9DՎ(Q_Eҏ2lJ]\_c@QIɠӬ\gu]dM ]Uzfm!Q۞0w#u1@(xӧ JC%_O hd3Bļ>uQUkBHŶV\2$$8%A%]5!&P2jkF2˫]A:.>nOژB4Òf<"L&10f{[T< ;{JFRM6.{yŲf M lw29DH 0'h fVϗWRnT$4IVN"쭂S3Rk:"pf$N V[hJDh S32U93,m DUo|>|}aŲ!S0h"lLb<n>#@XjPO&{ώ)Jطә1}8oYRFngl^ۈ=Agrі0G e@ɧL䓤9%|˛;DiJi{h[b??_>BwZH;Ao7a;% j]$''.dj/|Ώ.;9+FyrtO=qvqҝs4aXBJޤ8c}$$նURlX-_/W= *t|&G_:bI7A;YoIAjx hS;4)3^tˉ#FN fTg\_9;WE<| V,IJ%XV^֥Ԉ-6Cd9Nhm'QY&hZiP]zsdP:-3)1R{  Py*5 ADƵ bcwd"(%:sfL@Y ڶ%1?cXJge^O8m>X#?Mߙ9f a0`PxlXp}; pk.&t Н:춍55 ٶ$2"6>4̶I$Dv;d%~Y#2!uuH `cVŶvalj ƨ!i+0t ][ZI2Mn\.\W7=&9gImV ыHM@wA? Mx4'GۣӋ GSK_oE c8[Wρp{7N#]#K{\alFA-}QCLG)= I^ˍ:LYk}6GL C؂'j$U{+RCԈ8*JJqxARPsL߅#:o&yDK"Cn'}8p0 p`Gt<^3sE\.5сΙa/^חE Qp~>R@2fo4}H;a5$ѽiܦ.ۻ " 8s0:L5,B6lMV;:* `q}}zbv ;Vece xH6xˆ&Bs$)M%F^S{>MQxu{Ψwc#p?CDO%2i?L # I—(bܨ0P_( ^aSEE[-{(r]l޽xXo(S@j~feV=P#tQ*wggc@dke& +6gZh|왒$,Pqla2|N"@mi!ċ;Ti#;TԘpVgtT B@5~DkF,m5m>FGs N1Uex쌺XL qA:t~XXVK8:# h`P^!Xj#e ! I0$@3C{߼?X0HvF:78%_`2@D=hu8n ~8ι@PCu+қWZP~;+*mI-Dt=:U / Iv_ЏއڗݘPL!DMs CPr$cIV5!Dk&zTіAn' $csw*S;u,|z(tlVunz훵Wj[_0Cz9j0.@MMUc,}31@H`)ҞDd"j#X2k4h!M4嶐?0a{3#y?_< 6YºOvV[,V~0:IÍFh {tž3$1_l:DMV[K@tf,P[v$q{UtJAEgJD6C2Q޷!F1O+*WΩ:> vAK-T&RApX 6BFAi9Xlz="…ڡbԂVw[ݦ2ԫ+ݎֳMG_ +mkQ(!}m$ȈmIa*H Z܈nܦ?!i $DC"9(7뎟K7[vr Y4z*W+5C2?DXUkQϖTm@L?^%'ك #cGDLr R zEGw ܋çU~8=Ĵ6?o{\kɞ"Ad`;mda#yt=MC6d/?|û|jC=?۟|-L|s7p%IA-/W[x V8H(䯛˗>hǺu&~yt~iJ3͏҈ qt=a=p?DgA ?=Żqzbdz1n &Ӄ]ZR n}ܱ 00X`Ș8 @ @ @ @ @ @ @ @ @ @ @ @ @<yIENDB`PNG  IHDR ';65IDATx^u BQtO= @F_AY%1D$Fd?cIENDB`PNG  IHDR IDATxcQ9 H1+IENDB`PNG  IHDR 0IDATc`0s/x8 P`g(*To_4S IENDB`PNG  IHDR 3IDATxc *Ǝ@ VEv|ٽL)Ped\&IENDB`PNG  IHDRW{ IDATxc)wCuIENDB`PNG  IHDRW{IDATxc`?#*<IENDB`PNG  IHDRW{IDATxc ^ !!WIENDB`PNG  IHDR  IDATxc ^N4IENDB`PNG  IHDR  IDATxc`_ !daI^ŝ0IENDB`PNG  IHDR  IDATxc C GTIENDB`PNG  IHDR IDATxc_$bܖpIENDB`PNG  IHDR 1IDATc`0ٓ?$20hr==}2"0I Z"[IENDB`PNG  IHDR 8IDATxc }9Vy5mdJg`o q?#9IENDB`PNG  IHDRW{ IDATxc6g"XhIENDB`PNG  IHDRW{IDATxc`5H+8;IENDB`PNG  IHDRW{IDATxc ˜17lIENDB`PNG  IHDR  IDATxc_ #pq1iIENDB`PNG  IHDR  IDATxc`?B888LV^ҊuIENDB`PNG  IHDR  IDATxc_ GB IY+RIENDB`PNG  IHDR IDATxc_$YIENDB`PNG  IHDR 1IDATc`0ٖ?/20hNr==}2"09u:IENDB`PNG  IHDR 8IDATxc ݍ9|y5mdJg`o aIR?IENDB`PNG  IHDRW{ IDATxc4bzIENDB`PNG  IHDRW{IDATxc`/*O]!IENDB`PNG  IHDRW{IDATxc |0O[{IENDB`PNG  IHDR  IDATxc }pqe%IENDB`PNG  IHDR  IDATxc`?!_d3"[IENDB`PNG  IHDR  IDATxc B 8:WPkIENDB`PNG  IHDRnv IDATxc@aAP]S H$0a> IENDB`PNG  IHDRJ'IDATxc`E@9? IENDB`PNG  IHDRW{ IDATxc`E@ yIENDB`PNG  IHDR  IDATxc`Ew8CIENDB`PNG  IHDRoxIDATxc0Nކh,S.IENDB`PNG  IHDRrH IDATc0NކFm7IENDB`PNG  IHDR iIDATxc0NކFe)e_pIENDB`PNG  IHDRoxIDATxch,M+u~ (IENDB`PNG  IHDRrH IDATcB?wIENDB`PNG  IHDR iIDATxcFQ^'^xIENDB`PNG  IHDR [4IDATxc q@pBOXwIENDB`PNG  IHDR((mIDATx^ر 0 DQNH!bA  % ?˕-1nIYvZ.L:7@e`d=G J=hY7`a4@ $p2@ $Yh^bG e @!A5IENDB`PNG  IHDRa$IDATxb-f8;>L Ayqkk@,r `( ·Ҍ` _xe T1T\ۡ%@B߀'_LY@<}8*RL,Z4j`6(&&q)b; ~ ĿK [NhY$ @l 7 h_EMB` {@ /}!!!@S(}*M? 6N H0r?>Nֆ=2XPu( >/d*υ,`?;IENDB`PNG  IHDRaAIDATxb?.l<'>yfb30LLUR7XL" \sA,]H& be+k ԴDCX 6" fb.0CKx P[(+@$x*q2Td;Y h.@ ;r'K#M_ˣ"Й@jM_$:=JQ* PPPxc@V J߇Fo ~gS(}*h|?PCh"u0N+iz IENDB`PNG  IHDR7IDATxc 0F?|4PwbHEL [DIDlp7HF4f+:|9/rK??" ?7XH!PwuDV1|q Vv$ao(DxJpdafc|IENDB`PNG  IHDRnM&IDAT8?oqrp9q\DtH-'$" :X$BY FޚXmU$%5R`zI'|I z f.`8NU:έ/.G|](]ixIENDB`PNG  IHDR&!Aw@IDATx^푱JP@u5 q`CTBp|;(tssi$/ tp,zx. C&ڦ(*\?fTT!_BbVŲ,͒'fK7Ys,Qqm*njۊk& c,9 `@ZRvC@L.ľ)'Ȱ,x}w\mLc9SݩB=;b'+`>ujm->jfgUnZc_4if+ "̠A32 R$`4sZz'b dL\.䶍%?3b R10m?,^IENDB`PNG  IHDRVΎWIDATx^_LRqŋ.f R7STКfkSΗ͗慥R9}l*3jleUK/E67P|(yi]=} lv]+zx AK0R |FBQռw/Ԥ434<ܐA6)pNR LVnFj){q7;b-gHgAp 7# IENDB`PNG  IHDRVΎWlIDATx^]HSaw6[ WPUPxUw}]^DoEDiz2U4Za6f#FDjeԜdՍ%j]ux`]ygy`gJ.[ (X=Q/fĪ@`kg#Ey C)az^1v @ã[2 ~(~w2pCYt!In0v#[Zzn99ι)3D3EYtЕV'cqUXhi#/;ɪ }mh",:CkӪ|T{ft.chAYtݔT!BW̌(pUVUH'+zIEdatgfeU5zCWccE4(84V^ߜ\o <̡$;Yt +YC QŋyI1H~lK[8&JH Ц+cZ98~ P8^I"6+V>/a@-qVEB߸7ܴI60|@3 pL}zMO,lD{G;rcҥSS&ΉeD !lW6Kz6ǫUTc φtO8ZXxB c!%|ok̊6uLY $7Յژ7CS6$\ViKsNtq"OMCG.2gIbE9 }1|g.Kv}(wR&nbHggιgq,ɱ1pRR5 b4cc)-̂T*qlxKl+u[p"虥[Ԧ$/^K̙| iQL?ĝ7r-qM/lWNO>򳀄ץm`pҠ9UU /]x'uwc\"fԯ/̳X!D~?sA+ŭc;lOBnсaN WXJ^GDH 2d|2 !Q'n"".D eC8 /USpϦEU)lljx[:zFw@ڕݓhK fpnծĕD| JFӻNq,o8YJK|+oܑhJj ''W?DҒpGEA)90,j37-'PĂЃ$U/%[2!/H9SW"B@t¿ д v |^ t @@ (z@@@ PDzs @@@4|HƁi=}~IH$ L꿷K// ! 礏F !FK':;;VX,P:Yb~Lt1@ c$FwV用M;ͥP G<9eb3ccw9ugX{\hch34U:/]Ϳe (OwӦ/oM_N~.ֿbkFN~ֱ#@?bskgBhqh/vBo csoNcK^fa$jvEc[+++O&7cK!,(h [/YckZ%O A(--H־ ɏ"|cc㛬]:PPF'0oKvM^K{E㗱*~@ p(+r@UUN'Eԭ F(v. ^gO]FXl{;H į?P 0@ P -? @@ (t(@ P  @@G @@ Ph(@ Ph(@ Ph($?@ #P? @@G @@@ (@#PDsMЂ GRf$ @dհB:S:?;lޖPk,QXX`5Ba# M ) #>fAҝ  i1 k ftuP #mX~=DpeU.k0@8H ,<ܺr';T5KxpkED : % vvRDa0>& $\\T np N53 /1_>)#EbNAu/BLEɅ <N1ze"p/eL&GE| 4,^?qQS*̭rNtHjFA0L;"q-&K_5-h;=A`vQ) h[$ݑ*`XyY%)D* <PN SB>weGvp @S *\Y#:q"( Y$ik$:G~=( eϾ 711i/7񈨚PC,kIY?^ Oje^UR k*C .-T=,Dw#}4"98Caifw"R̂xpKk2twYX0گ^E qB_8|Z7jp}JzBOA8O`%샹"Hܹ>,$Ш;{djX ֙b-|u3G.Co |pA C,pCb{F'hy, >iMkzGp۴wEL bH֊ݪB 4GOHdB냷Jpn]%e- >m.byεJlH 8#gnmם}6(E?~CR9s 4KPR}Ո>au@Ӵm(? ֢|B Z_v00 3S>}aAM=@ Жܼ `9 zfwt4J|yGί*,$&|pfaf_[ eG2\02ѕ|LBpWO YyqAbB wPuWuT6l/^. R,>꫰i+4ChB/Ѹ 2֧`ǘz9.1o)fTк6b%7(CAP#>FFZD? /+^,JXѧXߟU?}]zgx>, !fT/rq> /J?3'?z) \eV_FXEaW4x0^ B>'DuYRʲ̬4eT!(\૟`C[ܜ ))7fB `vI$G6(-2|a\]Sll N 3zo.0ϑlI8{Y||]L^@@WP+ |'&MyN ˂m+3QX\SQ'W:\Rv 7:J,Ձss|(4To?/Cvャ8K.yC :[dZe}ܖ{z]#,F ^R[h/ \X ;AhQ Wdx=@7N]Hb0,bQ}yz&QOs2 @wy 3O4)^<h/ n e»ȥ% 1*7O>ZV/P5f9_zY]Ӫɷ0o?mgٴVX'*u pt]=evyo7y @pb8Nd0281 4BcZxO 8"5HDg`s 3^DÅ)&qE 6BQ=u.1ˊN |x/ Bl_I _T o%؈(/0ie=!XSZ}lZFJa=«'94g?|*,$ zE)2^@в*Yo~E|)PQ|4\TzX˲^^a:u$M*ژi0Ea ~0: 3ORrc{nMF_N%$ @yZ F<$=cP@Yw]@z{C{/r%"</zZ\+.{=J4tBE$1{&K4D@cZfHSl|hEZ1Ì) e^|QN(ăY~)p@U4)+ 8׺rPH{;^'y/QטwӰۃ? gW76o IЈ >en6/۝b J2QZv)/64>/ZX ^Ӛ\ O_D 1N7ZЎ"3vO,|?p>fF`g;`xhP/"P IU5+zpOjƮH]cWH@CΠ eM_N)/l^YozuYW }w p ?x3;uE-8S;ܹU@T&bZ-ks=Kh#:KFPYbᐢSm0%;Ƃe$0Qt>G$X^Kjan1WbkARD3$'I@[)'wT[? $$ƫB6Y$s`Vb|71K>XY  WQIyC0;&Hڱ"P9 ( DyO^@G%2^Hp˵pu09!SQI!@_oP?^R \܀n3aBoD!Н9<3kWZ$sSkIBM Bfa> ${IKK* kgeee3j_߽쇹 HQfY_ϟfAtd<\ ɷкA@l\_ey&y\O[Ȝ/@ּPR*> >yK?|~ֱĚu{@_#VQ%rӼ6!9$Cb`,Bk~PPYX{0_ѧ@ Y~vtMn&XG4>88x<$ד~}jW˨0i YG w2qL#d!!X0q ?'C7??o~C0)Xgֽcu- ]B\YKCnbjC).k-ĶְI&q".2TK e.,xM,Y'*&3"ӆ!Y 2O@X```yO:$֜8$m]D(|MKTSkkǖշBDqMyVK=1A|bS{sȜ![e;n% YK󽜼2ߡ_waDmoyW'P1<~b3AK2O\D^ʂvyetBSYfJ&Csl/|j:i[G,+o/"ق#|1\b3a&g,J- 2k 䃛4)fAY[o_ CʉqgRP.G̞;Fl\|s'Ex!Ex:;q3%9w`~X?AHlb jP}0sΞ|`_tvE˂yCeVSm3{Y_v<ʐΛɔSKym? `Thd.Xuw"uJ}&:/DjbȬ"o0< f/@RYGɭjrJXKw˂n$ (ܱ~[kvwc_/E X„ϼ!Z) 8G`/,9P(W+u I~Oa9-B ڳщnx&LlIoci:pR -^巈 _$7 HEw) p*:bF 4t'f`Gh/>5oܻ ^o~zx Td ;XXkbp鳤 #%~{!b0!Dqpe#S< ȋ" ږ9ʂ.~|^?Iq\f;Px F=p w-ʸ< zhHdF2d3ɻR{6"P8TPͬre# ?h %%xIKY0`ڔ_9{ĞNEL>F= [B%7AL8x)]>y9k7}tLZၧf'byަD F6lw<ؑ}/;ʰfGYn{*].*L61K07m&9]Gt "N(2lPugY ޥzER [iHW# G4"1˰/{sC0n9YSo'S$V%PݰM`=#1/]0*A"cad+gvA_w MFK_YI8'(u->F`?JTcI'."0'mx%>ϝ6,y-h>bq@=W>p's|vL3r{>1%d7*/P,0 U5푘忦hOx^[-Ɍ/BྛWt[~&Q|Q0>"Po^CBʮS&g N`6nh3_RېLZv | cL?.+~Fz|~‡K]! gb @ Ȑ?_B:b#ݔb>/D46͎>L/)E_s_6Zuոh?g% ˂maV^vM&3 l"*iY_I>“#Fl見Ɔ_O{Do |y7r3P6KXOض #=RЎS6d7'73GFׯFP.3SS`+!ܨmhgaf!(5-(BUtHw~e=X \]Ҝ.gE~ oU`twD25\7KH3V?(Hl0yy Lxg )%'L !{[$Q~LRj 0{ oq@ K<{n_su;_kg+@X+o(bQ=Cpd$捥YwB[{`sMȃ-I{ ̪OO b}`O ,#n9'aG:Sw},}Ӌ'V槜cG?b~w }!(;&\3s"܈ YۊPNN!eQ_UR̴VZ0/":qN>}RʹzB@ʋ5 Kr#,,F_Q׿H _cǝ1IOZy"b9yjɞ38Lx.IDrԥX86ݞ߮䪯&Ǚ )cP%lmoA S;`??I_Q׿ ?1bS> ̔ݒ:X}]p߳'k$1pbN-re`އ; $m'VwK/m7W/B5 gᘪXw'ۖ\_(;o OJhgC6D5YPXĎ|IT@ƿ),Q+N2c}KO:P(;`/{uwHD .ay}=kɢmGU8 -q=+i6tӛ!OyJ˟g)k袡 A^m_6Zo__=\(| k  w!kvʃss--^;p5Ā=[&.!>05Dj`׸Ȁ DŽ%3J ?>6໯xЭ~AI@ {<@0d>0n=.\^J"ur`O\Dܣ*Cfp?k^;WYՋ^70J-Ǚyb Kbk @2VA(E!ۦIJK F}{|o=(_@Wd+6φPr9ɝ/G<}vLjq ^I^ݶ::; \@޼^ ֙w[p4^{D!=\*_#NAeg Lr\QZgĦܽ É^ԴQOj"L_4Yɯ;lx&Oh|C۴%OK$?zz[P-V<οr\rri.PS/pnx[˂ã00ܝ`z8Z<߰{k6w~//YGF" ?V`wH~ 2{q %[1YhM[ NiS)wSCi~pO 7x=Z"UUvx/' λ4/k%UHۊCb2iMX hD-GmʂNz{37-ɹ~#Far[`T+Dr&ѪJLF/ nݵ |,qS-sV3-uέck<:S~'i{3^=y=u yKRs&6)BT/Ihd(_-U7U 4j7>(S!H;{^;GkFEߌg?><(-C$-8:TU)@m3龱_J/f..{[8dt@R_|'h;$Uo4J{Xscܳ2ۯRV];7~߻Pk9x"<eE@]C00cLrߋX"``ۘU'?m۝u{{;E]<܃ImQȬ^-z?gc5߳Hs 73ڇk6Vʝ )V [F~MBƷEε=e|:4XސWvR~ d4@[pz`ˉG7\pܥvl&S"GW|U6RǣMPoFC/ f˂d7 pu:b?%/'[Z(Y: F&@0 N ]O}jVQ_i epJWZD ZPFU~XmoppoWsxI(#M4T 5bGυ{FY( ~ _\e~ Oe8X~±QK ܽCDAmF7nֿ(㴝[mM\MLjurZ%  %5|GTF$`bԡE@1:rg1% [O9_+D\"`kٯф8v\jq_P $Fd60R>pQkb4Y, -6PvJOjs^1R^y[U=SQ}ybs͂yϊK!<@#/R~&z~w6qV=@!جS:޾Xh|)US>::'Upz:k61zbFӫ|j8U~eڽ]xy P=?^<84WŇammMEڕ 龍& ;LBxC.{C`*]X-i9ls>q^q~q1=y722j9._XZZ3Q$9֩D%5^aOKH^;25Yݓ ١ϝ\/+}o^Y@oؒ+!D p%.WcAޕL~Y{؅4muϧi T8O{[>{o$IZVhs|yq8[Q[aja'Bг?J}%}+!(@ @ P @@ (@ @ P @@ (@ Qcnv`;IENDB`PNG  IHDRw=IDATxVMkA~fv7MԮ16  b* xxA(E j$JE=Xm;$%lvwtkf}}wvC8AC?du:׫9eMu6nA~ΈIX,kkR`0xSp"xiƘ+VSdrF(-]hRLvPyn7m#9%bk9i!cX7@(@ RPCrW_L hg2cLWD͙L-祸;9NUY $˸>هRdL|pH8cCբ n 60WWlpv7pk*»{p Y\)uR 82"OƏ5DJ>4ɛ.o&r zPbP>$CU^ O /@O^|HH dE.S*%H"#TCd8 iH^ Wf}4gKLݼ)bDݲĈx evBUáL϶tP͈7M_'BD`0iîd6D]яVkeiL0{wcNk/yR|}BM/T]9ZTEN7̹F$[ZgXٸNFQHz~p%!]H[E:?5N`wMIENDB`PNG  IHDR szzIDATxWoGfMC\$H9PUEETĭJz@=WQCK[V mj*@T)Pۊͮ;Ǝx{gv~.Rb=:u\.ZRW?AM;|#6 cڪy>p-| ͹q硏cGm1uq`O@fFۋeL*-]؇eL= c`MDMႃoR.8)$T oV^_҈hA'O1qţA0YS\ly8uf2>'_a~SVJjc2e2WiPR/EHA *O p=Y2DpEE(::cUxr|=iԱݱ˘,03 29|G oؚ4\MzRMZHLWK3:k4ZG ueo @V-<Û0gçYGǎ@:k\otB#E2ʮnk ^mg?1oŒ0L<KBGk`e zFrKYF06Al00WbYPPfTEՃ3Pu*{bo!MW`,d@׵-`ː&YKP.88< 5 ^!Վј%o Q@O_&go ۰dؖ` +-$#* ϲ%!*y5N/&/ ^w>FeIENDB`PNG  IHDR%%Ş sRGBgAMA a pHYsodIDATXG ١#KH Mk%y0#^3ZXPP6 2=^:݁R;lTP/ +Ӛ ,b0S'}&@IENDB`PNG  IHDR%%Ş sRGBgAMA a pHYsodIDATXGK 0 D{=9Ѝd(~F(2 qјhBkBm@C(t*4ES)ZL˲M3ܝ^֤֙MMm;ʦr?n@S5 %ͯJ\R=Đ& s77@.4Cl] {Joz [-1qKhofPh3ESL&1!jIENDB`PNG  IHDR%%Ş sRGBgAMA a pHYsodIDATXGA 05A?{xdؙ!SVˆ1_kWh HxBS4@)B sԶ,uk̠v9ϥr_@0$sf(9 _B Wc)]08K\L!Y3Pq`U] j oIJKVt~"1|6&L׾pupY7)G М=)j)MQ( IENDB`PNG  IHDR%%Ş  pHYs   MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3 cHRMz%u0`:o_FIDATx1J1_Tx^@@JnE+k( L1 v6ayy$[,(P@P!UqL:NctN#G1|Ơ젯J 0VkQSSoOX%gaJv_XTQ |%~pkYizj@J5-K5FF9^ vcdr=>X᭯9us瀪TrA-P@`P!Xv8IENDB`PNG  IHDR%%Ş  pHYs   MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3 cHRMz%u0`:o_FIDATx׿K#A7 a BVHvLa!vbm!ZYD\y)XyU-XE @\I63ccCl<.yaޗ]U0caK$J$J$\׭qLFѶy$IC_8&{oNeBzwsnm8LjR*Ba^DQ4ygߜzn;tʃ[Bm{_K0[Vk(q>1V4mc,8Bj2W*|>_4mRO9:dRJ5~5\46@$J9 \n)0 /I4oBalζEQ#iL|R!n>!=YuQTeYuW$%Q%QPIENDB`PNG  IHDR%%Ş  pHYs   MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3 cHRMz%u0`:o_F%IDATx-KDA]D6(em&ALvA1 -&E(E"|mb2ɺoX^׽W99癗UӀ*BE"T6^B bk\a7h}U!J8pKBk@ /h` ǘW*a [w!o9 T#,pT`'Tk%LcXdj:VqM<R)xCL]/|T#+SLb OS>jyUؗy<3Cg޾,/~]"TP*Bg&+,vIENDB`PNG  IHDR%%Ş  pHYs   MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3 cHRMz%u0`:o_FIDATxAJ1'V(=p%(=@O؝ нgqeqW C'$7Ib =TP*Ce B(cBĸX1FQS9F>J+Klx)bL.pʽs*횤fgPCal,>}tO pMcY2Mj;=pj6j|.+ҟU/ڋRtpqq}i?cuٷ`^I{*Ce 21]|IENDB`PNG  IHDR%%Ş  pHYs   MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3 cHRMz%u0`:o_FIDATx׽K@wBKɒ!2-]t''qqkW:ծG8Xc H疵\i#4ť1j ro?znC!P P PEg]tGW\n1֚+11'G'yE\Qq `" N8&sAI)545u=y;z8fRJm:x~P( w'JWQE>캬jh3{)!>30 a3,ز̠LBnLD>MJJuߚF^!PIENDB`PNG  IHDR%%Ş  pHYs   MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3 cHRMz%u0`:o_FIDATx=/DAߵX%ρ'P"[i$DQJ4T hH( JJPl,SF[̓LfrμsfdW2)TJP *A%(x;109\#e v0%죉5| Fp3` /E&`*p EыH XʰQ,ཛPF,m5+!&jXih+uJh`>ڏ?8+}pQbYLG].m#EԅW=TJP *A4X*IENDB`PNG  IHDR;0cIDATxڼMHTQg#Jp#t&!(ĚMOmj٢nZ +"!* E)*kU.E`ADj2޻Λ ?{9qyw7eAt?S\ċZgE"c]EO-󥸅w^瓴&'ވEn8-GGhExѶ7q"6I4X&- rދuysvU1FVVu *LN>~iӬs&6<٦3ؕ^;A&z*Z/->$Zf$3TQ44Kږ:ye|Q#D#2 Q6wT̅=_6-Z#)|E,?8aO mf4Io'eA5ndưILc#W,jJjp,b.zqYr$a.w9a;'h{6S?Ta; /Ő8#/6DAl:X2e61sW.<3^'kMLQH'en,d?m OLpeIENDB`PNG  IHDR;06IDATxė+Dq^Jy$sD^Ê"b%"Gbo#yĊ$ $#Rv#E6Ɍnc{;N}iU?,^> M)ԁ2 \# ٜ\<`PRH{ 36L k018mhF yPh81V9V0k_X5fy`4?8,3vX8 AZw÷BoDX3>u洹;@1nzaɯDPNҪSD h:-: \3w+l:MFi%ZU.-.2FcZ2=o3+n_-KSeZdtg'"-LI$$ "yXϴ y+L?; ^K۷G?UɭÔIENDB`PNG  IHDR;0IDATxM(EAxRlVQH[ JY(ʚ"("_ b+Y([H39;sgy>͹ι3+b(EW \Z Z&/0y,~VQ/dVYIENDB`PNG  IHDRKW pHYs   cHRMz%u0`:o_FIDATxA E%3X5 @ 31Fήn) xbgMj%bm6MzE=dN'iɌP&tH.-=O _堡_~lϚIENDB`PNG  IHDR;0IDATxڬKlQg>Sikx&%Db#ll<6.V,Q"ģ4B,e DDGhDIL{;_z_2s=9/84H,+ *f2b ރ6cNɘ lx$ fXfew1_#QaQˢ^ՠCi/RogepLuQxFD'[Q.sPTq_Q zHڊzNN5CfK('ΕB:0<S/f12"\ʰxzU6ql䨇uD+xt$69C[I`'1 &fwmTGx}~Nɤu~{mPoXvfG_}u}I8w8O sJjp1:Y̸~@zp0։V_`jb#8J=Jh?%eçk-X W齫w})~?maljm?϶Nzljh;v[( "6.M7W7qהGyx0Y oW`heB:c02[Xs#J y64,/> _AObdEQHSuk\9QUOLQdGHH $=w04@Mq,>4Ϧ  ,\北,:eA$h{5XtIIENDB`PNG  IHDR ֛^?IDATx9HAM), i4iRh#D ET;+- NVQ<1" Q#(""RH ;CaT#dfۙM\`4qQ &. 0F^n`b:W!!e?IENDB`PNG  IHDR;0IDATxb?@a8?Ķ8 x1)gb5 bF<6jCh)Y I@jG*B4r!db2Lb VnZ?Hh\pǠ^\6Z?r8->Ո ߆F\Ej\Dh'1Tn@](cPNŠ4qka*?]@C^@Hy@OFvJfadC҄4CjHEM b bMZV* ˀX*BhZg-K> ]pA-9P Z nqt Oto`mmˆ_IENDB`PNG  IHDRH- pHYs   MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3 cHRMz%u0`:o_FIDATxڌѱJQ/AKk%SحZjVT[)jk 6 yX.ifgsEQΰ|!O5!Rc ӼF!BqO!ѝAwq:_21Gɰv \./8ЯW8I.p_(IwcC\b9I$dyhaT[ buJ˃gosS-sXIENDB`PNG  IHDRasRGBgAMA a pHYsodZIDAT8Oc4z 6\Ӏ3`9׷/ 8 Hy yp0 xbE~kd\ +`>,(=,׾>_Zex"@1ܦ;wЁ|@6؆^`!?~TտA1›k|3p Oᓜ;|A1^ a@ q@NǦ^@b(]C:  H|d (K uG/(6@b  (1IENDB`PNG  IHDRaIDAT8uOh\e7LAIUD(B7j &tV(Vp0҅ە"FͤtTJciZVmh2mjL7]15\!0|zb$On4oi\6rG(xY' vM;7ݚln^y_!Էkg !X;ŧR{[l?3uPB@}.3I.|_K>Zql;V\'enJqU(${qircjjBXe.=Rm\6RCk,t^#usZMD^>PÇsi9 u;ޯpn#<<^"'VL<&lgSB|~hV^ZrGIXz/V/X}0z/&Q- zx5a0/Km_Us 쏪7~ظ`Q ǣHgL#%L`6؟ 4bDe_CNݸX }dcA L  |7;#htwݭ+0CDLyGTf isX()m}A~jsKپqm|DEIENDB`PNG  IHDRa"IDAT8KHQǢ6VTڔiXDRaP(\.jQ5 w- a…L 1MGPLwZبS89".ksW3  ҥy 'Ŕ4/CËY tOI 'Ŕ.;0|:vA4Ax`ە 3o H0zZxlOH2 a&FT3?tiO]Ff~>>+sAOWAOW?d,D"eeng L=!Z@W?btnۮ"UcơrȆIENDB`PNG  IHDRasRGBgAMA a pHYsod5IDAT8OS;oA>Q[?g'YI9.C""D _P$$_@ *: ("þaf1A2'73CtʩK58>˪/+W 8'n5^Y>%^!kR?1^QP`W_;W}#aJ;(-jԞmyR }~S&T w%ނRegG695nnu1CAb<ȦY">h&y1"UZ#";vL(9\c"jN%wNzlLqV4G!yл7 fb52 緕I*!oFqw,DpAk;_#"Z#9pڽ=PRPK߉v]3@9B!ZOSuzO,@ԵcB.)b0Uh/39^;xEC6mFw`[w.[ c%jD</P)x:2Xv}{ǎaJh09By-#5-v7IENDB`PNG  IHDRa+IDAT8N0FJ}v lkxHZ!kHy51 +[$3c#$˖g dW/\e(D| < H@71^ҺYeOg4I rU8hrvp#j.[ܝeC~5קZ0sJح=ǽml:ȑT͡跷 ng`JUـ`Xn;TY&侐MOg,У,@}&Zxe(F=aUbijc7BqeIENDB`PNG  IHDRaIDATxb?%Bc@\^@,/xwCIzOs vb^(*@8!& ` J ʗr';%@W,c<,V^,5dqrx.q6[ @I@\@Ai6p%èX g(- ^ 䚁'B YĢ ~48IENDB`PNG  IHDRaIDATxb?%+* %o3 `BNs vb^( ⟂cwPRH`M孀: ?J M3@ŧq98   އ+ ā1C/XXjv "`@e@;gCCK, ދ3!Ay!OP? 2{ Շ0P<3 @Jf@n kك5\@*6_، ƃ,IENDB`PNG  IHDRaIDATxb?%Bc0ֿ1偸X_6 Ț7 aOs vb^(*@8!& ` J ʗr';%@W,c<,V^,Հ@E ށˀv b+25 @X٠4?  rK~ @k=a\3A!kXqs#@3&IENDB`PNG  IHDR"":G IDATx̘KHUQ'^Hޫ ,2%KB (B(H&l5YEV,F`%2IY4=R/,OyF>^Y{}:ӑeLd `3X r }p L>#G ] r )0X@?>$GDU`tcGh!G%.8b֊@8,.Y;FHuA>MI*!-xCwAi "t{˹3k b# 1C5">{l7-}%0׀`@gɒV2.Vq&X/PdQ^JյsőL'X ;Ȓ.epX>0;b"m Vgb:'$c)5st^ڞHw*4H8 VG=2rh{FV>0P-(֯m)a?g<%xGȐm<g:KgRsme?(bL).coIm;3~R"%R,g)Ѡv0"ڶ\+8- .ۺW+ֶ+RH"`L[mS[ҹ1!uڶ69cV<2MlTofcd_"F̘XH!mM۳޾'8!2f)f"_vybaIM{gNkϬb)z!&gamkuv_1ϭrx oMxI"x~h SNX))j{]X2ʪ8gSgRwT҅APB=}tiYrf%瘭䌳W% &H(,W#s5YY"Weg9,/o^GIENDB`PNG  IHDR"":G qIDATx̘KLQKEDAHbjbGb|D5 ,Xm1FэDkƐ@ %.>"Ao9֙;3mI<ɗigszۂh4%`@%Xg;<wA:ߎTJ-Ƭ" ~p$ xmS` %`N5 T^cJ)6"U`S \}`b4y΀ՠ'vUDQa Qf2wԻ)u;rD(z*Pmhf1c%y1J@L}{`+ 6V u7yҵZڊMJN&^ 3Q'Pʭp6:IGԯX2*NC3i;ӑ,VI3r#aHJ|1'#m6U0(7y}=I*9G:h ce4E+)3US hĸ)]/mX1JPFt,cNLȟLIIۅ%*jr-|, !QQ8ᓶ"Jj\:”EYIm82k DmÑc9wdHEfFk&Dآ!h [EAr6DZDT ,(2oiߓF4k&SE;w{}t{ͽ{-Yu6c2nv&jRnAZ1!+/|9"Jgb\pe/"vwLSk=pC+7b׉ kNx>{jDRsFUg]Jkɞ']doZ/s$+"wVw#w|qҋB’Q(/6ҹXJC:HH2D ;12fZH]LxmO< +RGD!7Md:MvE|p5iS!_PF5V0P%B֯ 5ePpijjYhsmq+ t'Ck3*>vp-C. +.8=rq mpN|)M OuQP}W[*"H1%׼DIt=H:սFShe.;%N@R;Ec.߯Ğg 'f=K.ƳD;^IENDB`PNG  IHDR szzIDATxbcX0xċA6Htq@;W@6 HBml Ud f0?HmQ:`l"XCwHbd@0t"@A2l3@QVdHbd F!11ِ!یhduhdA`a^IENDB`PNG  IHDR szzIDATx1 A E3lѽ[)6^@+;q,!! %d>eTJD`&.`^̹5&X`- v̹52$=WJЭՑ݌:}n,?0_|_*l -m`JЭњі&ad{sk$ 0qw[#H@1@` }_FiIENDB`PNG  IHDR szzIDATxbcX0xċA6Htq@;W@6ot5:xP6f0Mf01 0uF0(LpI. yl3@Q3q, &E# Pe4A*?T=9d1 m:`m6H YPQa8IENDB`PNG  IHDR"":G IDATx̘MHTQg&>w΢PL"b2*(ڵtS*djWHk }P>-h]?z3o^q@?{9/fCKaT2yݕJn_[ө6'"hPS*IcjL~_Jf5-V>e8 (fD[n NyVqh &HQ(0s'*z 1xȇG6!Nmin)ڎF=VәLk߃\1>~D9MY%a &_!J>%AD+po>{C5,1' _$hee|>}PBDb1LjF*!):^]6{.av˾Pȸ P{۷#dھ#%2!_e\'`vL˶6۷#dRs*~r5lߎԈپ#bj#G9[D!6oa2| 9}|/@N PQ 6 0o۰L}2W6i15eaֺcT$*?1TcdzԱnM\*^[ f`'ALG91kFkcn܀㈹0su߬m9ϩЭZQӮ3j93:ŵ.Aם#gDLMkDDU؟%FY"Gx B~IENDB`PNG  IHDR"":G IDATx̘MHTQ}SJf YkE!EdTA_DLٔ6Y+[@D"p3R[}Z$4.\ޛy̅{sysL&SQci!'6AֿGx/1|5g4_c.Qxl UH,tC ~k9u`oSԶY8 "x"˜-=r"9! %;ߥa͘!XI8 cy \A yðD<- an+ԜZBo!r+!"|i5I̍ "wd(f`rY)1#"]}D|%#pȜ'gnWޱ?+0 Jk EU? a׫#"I{OUhjS"\a|t{D'jLL;SխiD{` v[Ĵcj4w*g;!1hW8X  =ogTV0ɠZɬ3Spuzns-Hc<ψ|O46)~Dۙu-Qk2`!N\`qw \~IENDB`PNG  IHDR"":G IDATx̘NA9"DDЙ= 1jg%i6bb##Z &vFQH-ݮfͮjyy$0 -@s44N_G7OmodImhJrC9*0f :vO;"wO~JڽH2JIP=@qGb' C>T2 sV6" `?Ic*òفB AB4/1Fj[;YcҢ4v$AL &AbAbŸjcdu1$6#U9,$1#yzL֠ i]wj*hRG AXg_uh˶C|B5!j4FC-BU ,uLni(fQe& \MMe3tl܀F$X-yrs-s-1A{%.=Pa )82IENDB`PNG  IHDR"":G IDATxWMHUA,$D%v+Z%"!"+hel#H(J˨U?Rg+SfEDF+E(7q{{|{gΜ̙3\u3Ay0\N%k" E3KH0@P\H'ҦU#Ⱝhg5)Ŧ.˰b3 l;$5tX Umۀ(GImV2AQ.')жcKk!}+HAX8bw6 ^[5A& ^$b: FkH  UE2~HV ٔ,ƛ?"XM;! wEm{|4c5[Ln)M]g+r8WΛ/\F=P'&}L˪ǹ[spbj!Na!9ľ-v[Ip{a;idZGKF˄AuS|>6O78O~>6;gRnc+t66f֖JՄD$N2x@5OE/Գ\px^Y ֔f$2Br+#)$4%NKB̄&hoY1Q2XM~GY0eY<󒋲{,_f'zX$W=RIRKT'"F9G]N-62NߎY՛Dn#Xo¤9G+{sy##ܻ ަ=|s0)feL,Hwk/=~'b,r *{Ri+1wOLPtEzVךz8*;$kHf3p)6N SiS#^IH'\2s{ -֔,Zto5xNIENDB`PNG  IHDR"":G IDATx̗KHAǿEYDYbVDm-_h 7=.LtQ &XIe%*Rk |Q5]$0]?8s̜3gUUU "Ww!C2Ygic[z YA`]ˇ`A۴!-._q'`J*V2f3 "T},t6PQgj"#iD+A 4mƱ9ԵŚ}׀`lo9w,  QaQX0*𨫈][fhK<ϛ/.C^bFCԙ9\wcU~f4.ֱ4M8L@%*N|0b+]ipz劔PFeJ63(H!Ru[?qs)`Y8-5$}Y`Rr-5xl@6D[qw5-lfl' ʲ畈 GfҐw,;t\s<'7`جѿ^Uƒi%"Ck jAiJ~JCCrlzE kϾ1R+ )  ^J!tKK-ϴM_t]Ŀ=L:«\1*??I }qehjω$g>+'c|83hz!Q&QtguZnMC)oWڶ0&M0X r!̲'xicV\%'٧JaDudjKmωޖFۤ3Bb%Q]?@w!'rO)"ND4bf̓&2F&9F8’'hϸ^M CxLYڦx(UaT& 31=B h=G@(3y/jMd ;֠$A %#X)_--ˈ5m>Q&˲)KZߑr>k *m3zp۾^Y§  c&B:W!>w񟴽@$|Sѧv<#$H @# wde d&a;0#pD^|Wt j+:ڌM6 50 1Oe_A u/R|wPv< 7GԹ-ED,@#F=3v V ߹lN!qxIM~ܼ)EϝQ|0րW!]M\F[#Dx6[vB.XʾX'B-:h!d(0Y˱ͳ8sW:AmK!]j+ˍ΄eG|q1w#`W}G\zUW]OT6iJ,t5F̖f:oJI;v!nscc7BP a|3!CLfVW'P>~6vyoS[aCDԫw7 ~E1u0c 9̪4TMjoS7Jk?A@!$辗u?k?|4ߠ vwȟΚJ> m?rF9_X-/i'IENDB`PNG  IHDR" wQIDATx̘MHTQ}&I¢E1ZM-RU 04H]41JP4tY I.tFE~/\sǹwޝ{oKR`E;y(LV98k]f;W<8b0 '۹ -ED|8&tBp6)a1sO1=wBF-7njlW2#rd``Z] 9+XDY'B-BțгΊb&_o1гNoND\Eq3!l١vCL,"t!ׇ4q_t޸mdewBx1bZ/bܬP޾ AecQyUDq\3LF~O3 j4~q 聗~ ^F*0O6fDm:/[|x/Ɉ/K`=]|(IENDB`PNG  IHDR" wIDATxbaL&2Y T̗YHTǀX;& Ķ@XHtC@Z@|9B$U:dD.T/ROAC)p65FCبXi uO IM &5DCt#5/BPJ_jbuaE V$A C@gCA  >C-tB5H2hˆxC[j=@,@C8Ҋ$3ZXoq).A BƵ11@eAuu ӡсFgjLzŒL*'ICduC {?h0IENDB`PNG  IHDR22? IDATxZ pT<6!" P%P0JA }0Xtp>Qc2A,N+MKH$D !'!;{oAr]`2rvM{w( 7HuWp ߔ&Achb(${7LjħDzu+bKeĭW15o篷s_%>bKć\5%2MJ2b?0FE[fx@CT}}qp$rk#%e,VzǏƟ`U&#& 1>ΰK$P|egzq!L` (qWӊ)HXe7^mbKMy٢ K1!IC.5skt\OnU1n?Kǿ ;bEk =i31`,X2 {Y3ѤX!.ژQs2Q8V7 PPWՁ(UJ7yGa?j.aўRHbY [)&9Dfkڂ5cRbW!1SZUv4t-Z#Di1 R7%:3z6Z-2)Q[05^&އzUάq8SiX vϗɎ^G':|/oiLBK W} Zyz~Tnk_{vsHDSIENDB`PNG  IHDR99 pHYs   MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3 cHRMz%u0`:o_FIDATxڽQ0W: "@]*ũ[GH CHbEQቆc;0MK ͔8^f8]lZNfspVbs- )B )B )B )B )B )B )B )B )B _ ml[7 4Xo+Y 40_nk5xf,B? GC_9v_kҥ!s̲{AfM8j0wa3LyIENDB`PNG  IHDR22? IDATxZ p~G '6 H-hVSVm::xxSǣ2⠎-#c&&}nȂʌ3{HX ?d>]:?Z,[l0,b.1%I zv&"~"zJ >#H#ˈ+K8%Y$QL@LL;įVqxxhcB\Cx4Iďo])""VxJJleӌT\W=R#=0 >r@K@V|e[z6&Ό8x86kY!uѦ՝}H5K{FăjXQ@P\N}O1{aX uIeI ? 70fwᥚQt&#[,M#)q'2K/{D;Ad2 ɨvdĵi\/b{6kT3"y+>nz}Md&nkEn22V?] ˙b~ I_8;O@7];) ށt/Tː^ ޠLlpuR?L iy{/服"',"%MV/G"XJ|$r9xUT:/C%Q]F# KeL ) HXW隚]Mĉv8r^/^<9cAUýÉ􏇌`Gk{({Eݗ+soQH(?,wF$؉RxjhlDiiiz& vϸ-Y4;T{wAJ͛pԔdIo1&+j[Y,~ F Ǻw$&Dd{{%Y.7%"*D-棪 |oԜnn.B"tr rHzC"";S |c:k~gp.l*]b4WiNI! ٟBd ӿYh4 DE"J)EZՊ93Z`XGA\*KB" @z.&D(zK,gؒf=F;+.T"Ū.i,CvR!d~K88ǫbӡqs&œ0h$7X#V~ۋ@ gP( [:}'ty~TĤ,4?tD}W=if]sp.t>#v}\mmV QXX"甠V뱂8xXzhČiFi'! ɪ9 aסZWKԆlգ{'^Bqθ(4o< DԓDũ׈b)0@@+iQ\ZTɥlФ?&vJ'F1J!@u %{Ө>xS>G:5 :VELv]|8x̍ue 0{Lۮw0l/ORP iw-w|]hi}'"f4!-nޫCemwkiso-mmvҶ/uoh;MFgxaGt*m(V6mG_kY/VsumwHy~Bt֯Zn0bJ]VȽ )/oUޭ64BRg⡯{R7Z^ˍA~bhEy0oRT )}KZu#jmg1(@>鰶0LU˹#SH*]~ *!ex?nlԍea@TuT]vc+]L)Q!m*Jrall R?P~_y'K6 9C“ҴkQP ~K񝋤I vyOobC%$}0K- +]0Pn3jmji>CwVL!ho叁JHmzAC 5mb Xj 8ohe ^+џPp@=JH{^BX`:wܱn% |4Fzq n~*3{m({Hܟ^iQܞZ_ӈ!e4w6Sq&gg[w~֎07_Z1Qz?gN*ި€VJ8dm#xkEKZmu3vaWi-M|B!ٮͪT=A}Y*uQ{5ꕯ|ejլTBP9f1s L/}EIgsʺf>9 *!a qaSJS'oUlT kO<ذ pxBM%cрuknS971/Nsh&SgOkIr4 )H Zx饗[oU瞕jJz!o&X﮻L"@Z6uV֌Zb:… 5\ziEYylٲ` Uj@Ν> ai=FB/"wOT]vYMSP!c9ƷBwJ.R)ɇE [űO:$uGo~o<_|'W֖]UUsJ!EA%5[*oV ZWt}Uw7o^*@$͢fXYψ[n=PՂ *'?IjժGjSv~?VxS*ޡPl7(Tw)k׮U>o<!Pt qV3.6)xmR}ߪuQ4 2')pSS6 FL}<XAIA0 J}U}c ^Oz{H0GA6E]*lj^wqOV"1+R|sQ?+߾"W_]e^/kS *!3 F?j2i*7[ng>n5mVkiS^)D^,UxHHu*E!0;k_^!*z8AA%@NvFhDR'-#ml}?(!=b6?Yj|Um "d5Ua`;|򒽯ӟ(oP"Q#ʛ.m[l迶BcF+\68Hݙ\/Jk mF=TҮn_C⹸KP]xl{/ U Zp/4˗W 뮕(V1Y"ASN9E}Qjl92 ̠UFڭ%v1Am]>?rmPF|ox~1 F2=~‰YK¿ D|$Xj׾nկ~u/SPIn 0!/uojPs).ۗ~W| sI"0>22-$-HYګeV.ԉV[\yttZ%>!"AM\+KA%k;^5HW*{b4u\ rs$ 3ޢAX^%ya5'8t"3uMyvd nR~ϟ?},k#x S4\Ql6õ*"޵2k&b2x94ޮkAL0"~ d_rc *j\.^T̍UW]Ίdn_]vt8 >M3y KF6WlR1S,@A%3\E"LJx}M+|ŮTy]Bp1Cy?yh5 TROxBD  n꣪E 殈iK❮k` ǑtiT',j0ub)H_k?7~Iy]]=TR+'{C*PӥüĊ*+WmFttωJY^pb0If0az2*F]!a K/ +n昊^S޴#W  .ʎ3p@ql-AIy/o_(8@yKэJAzXi!+HDӨ]yE!(hbyx'XTx) *1bjxٕl=%ZnTL7hO gΑ.mJ"_~1N>xRwK㾖rPPۂK{b"ff^1y9Rp[Q|wE( ,GX=rf,.q1uxb~U,B;(|^gJRW(6+`C8#"/YQ  kD( +d"dV މ>֢BҎ6"PtA+DJQzP?E0?I"a6#A fȘez/=SB($W>ʫe6)ӧ,M1%*I0GulB衒8mZbz Ŕz:k$~,C%ɽӳF1%*Sy%xQ,6 !PIr>jbJ=TRJ]`n4%C%U#b nBA%clB'Ձ(DIjUB衒.b BA%slB(z[ J ]lBZJ5H#t2}C%UJ5U1)!TR=^? J'cʑPPI ̵^ !TR[ yM@T= *sPPI(ϰy v+o⪿^Ȯ>!TfBwZbN'J|>KϵnW,6#! Pgj/me| m'W^SB(dsX!.j~O1w-;"PPIv-ӶG*BA% @OHA◯j>!PIqUtBŜSB衒 JRa?mBB(BA% *! *!PP !J!TB!TBBB(B(BA% *! *!PP !J!TB!TBBBB(BAMnm+k;:?+F7:nb>ނ#pRl 6)R^$mrFcx=Em) _9bi1c-r>ύΒ2NʹNMMGy{ bĬ/gXs9TX̮nٹp({l ڨ%bC+ѷ}St+k}>s#rTҊ̚lܜEKlJB׋4“w[UÞqﵺa^Ex 9YcW!peeֹI-vBC@7΀JPh񹂮/RfE堳lS}N;1Oe.rߌèO~vQ-I(Fxń^}ylQN<8 e aRm 9i\Wiߌ'^ t[[ x  j͘un /э xR*:Zh6/rjj}WK1@0m{%ޚZ\/ܴE5;-tIWtA 7mE^vYZJ!Yx~i)!EA%:c>8i cZgMW r>7^\l"#D1ϽQڣ6OqD^6r`L" 7߄ 2OwM5DԢ vRѡuMB JEc#j*SQRL"ԺR 5j9k[l3#:`p ޥ6[k~{UC0m&/w@SL& ݪ9Q}LO t[fJ❚0ŀ3o˕>cR݌w<+b~KHJզF-oRoy[! [œopٹbC!Sʘ֕kQG}fݙ]'KzuT3RM垆1QzS rWCT9jmfwكl5=oj3C$rz]ϻ⨃["gߠba>*3$!S#*/S5-[޵X)ѕ@J!XYYΕ]}BAAOu\HװlyIBdd5|y&5xK*WSq0Vs(H5)ӭ6&QSOoxS=Uc_(LkbPm>ȔʯBUIht(bU`y; X5I($/l\M*D.l{he+f3 iJ߯ӄڼ ר8ֹXbFMj qO@uU*FLMYE ~Nrf-(\` ĸ}CIq+[%Ů l|x+>ALj|!m S~ޑ 3Y+ zfD$x-~BH;0M@!TBBBB(BA% *! *!PP !J!J!TY˩~^ k$wfޔh%C1c"}wZ1V&]z2/Y*e@rLm&r =tzJY'`>[%BNM_z9z*mR;(V=6wZʬ%EK{#mK11EʎŽpAO{m/;jIM-m[-{jy-xY`Ibnd`e69nc1eL,/gaBm^\Vg|2:s1|hVM#-UPtAa}]mF gVuѧι`lxf@_l㉖~YxtyTs-)I*Ggє݇}Q559-tmKanߒzK$So,,Z;ꈩI p#"q l,:myk j}M g n"F8Fe,ΥԼ%B ɈSPCw!mv A li[Zl@jh;11dB^ 13p3s;5dc;ȀPMZmh1i\.d۠A2w>ۮ xFk9k%u9.P)1yQ 1T.\_TS(j*'ǝW馣33.ۇ Dy#|]0&JoB 8] iQXq3,Z(k >0@`Е6W*٬{zH@ 61: jޛ8fO@&lhfJ}7ĘfAy`G]KzPd"deʼn_%- +fX|?Iw`|?(5 J Yqg 2cO %B(rjwC*Y}7+aӸ"O͜Q E+0xX=r.˫fמ߂ޥ횦9Hf]jȲ:gQMXf j9C6A;԰ k,thL@կL#!B) yIH2@HOyI;1qg7=CN{dzNUq^}V5}~OkZ>5\_٧7b˛]3jge E5fxjzU6$QTĔ2) a],m:H$HJB'6VTS9ieMۮOK%TBt6E!TBBBB(BA% *! *!PP !J!J!TBBBB(BA% *! *!PP !J!$m7k{V$V=+O'&`d\+ u\m_b3NTx?i :Hv mmւn[}Jۥ56gڎcsvgmgzNʋesvTsYviSBA% *!PP !PP !J!TBBBB(mčF|Ӗ^m} ԟ'$=`Ln߈tzJ7+ƾd; Y97ĶX'#뜵IF/=K #΢,yvC!Gga͈u] e-r1ijO~r,xQ#jS9a췽'G~lr S5/N])/)&jF\xEKa}Џiv#P;;g Au "k{}B)(iFxn%"K6`m;ˮ?, >y]`yyx^ /rMϮ>Nރ {:` DKY]~زt NuGeKg9F:V!>N j*tlxpbP7,W lC\Ģ?w.ǥ;=/5r_ύh-9R`䣠vҦhuM{K cfL4a۳4]p"6yIL !nbČf΋:!44/qS\ǂ)! Sbܮ*3cAkV`y:|g=8̠Ѱfd;35 اb% #L$njn-HDtt3>:{WIre7E's 1.,/ݷ''"[Z8f,AeƹNs#"|_!+x]SBAa=T8#s'EH9}:"YuJ !5Hamx㱑9߁!*xF#xq5ȃ]Y9KldrmkCyHB*N3%[J\⽙VXAp9(um7K˪jXb&b3~gm,'c?/GJhT2Ay՛bj8m> OUD$S 6fdhƤAImtaAbR& ,pE<0/3, xʙ!jJq"R㭹7zGZqFzRE>1XUS 8:1m?A5qrW)U=o31a@ LwRx:/V]P+[PPK^]L,ZЗPX~2fGJ; C4Tp7P_G^ɡtLMMcR `{Rٱ~jlxPcI8ߥAi;[c^Ai}$RH?e>=?'I: j~J?YMTF/I{PaG-LnZ[2տü]ڿ߃_ cCi&f`Bdc$ T?K{3y|KբjiHCԞ5G5j^B]"eJe~_F/I;ڹ"}wU VQ g8f4:>MnΫ?@VB$8OL^FsbU$&ޙ z^+Cμ]PiaGXLZT՟Ѓ* Hr(3 Q5TFW{ޗA4l6`p9 ߔY{ۄ|H+[ׯ]MMB5Q`Q4bQs3-.J(jj  7)KOR-,-j/^MMBCL \Nɱ/! &~2om?? XcaIq}Z">x֊w{}J|#3 +Byg'tx^goW^y8's7v-?xq駋c9F<K_z饢P(#9,${Ra{(]'ŗ~| W*)X.QBahq7?:{XqE/ZCNXm۶kvqLJ&)X|/Eh~~^\p+2z\.$/T3PyV\8N#Q*{?(lqo~\WvGq!k[޼N<ox\g-yZIk5j(15sꩧWU(Y)* ַR*n^V?uӟ}3ϹK<}臃%1K† Ė-[}AâfUs`ewo2kvgu{KA^zOm[2a˚5k*F\5!{]mY?I);`6]Z]_|o[j px቏CYI'E ]PQGy.syXeuPI#(bO{/%, iS 8.l7xw-6og.@`㰔X)׮tQgz(+%e+I䛻ߺn,7*dWu=x;-ܲO8HxKC.@mVXܹs;->`uͽ{-4<*lbj AMqR?Ȏ XzGk{-:āmO =1n+^_cX5.2Q)NJh]uUsZ>}+a a&?ck׮%:묳|=&jDj.bVFJ2k Iɱ( p˛Cik֤5F>`*vW o'/oH=i/Ii*hٕu 1k B`$ܐ `]&z>;o/F`$lMJT++wĉE[dET X.sSǤ4c7 LEF2:&t׼MڗߦDJo%g/W?b^M"YL 0ZgZZdb|M|B 7艗ߗvLtSob1ai>%W`wCȅX}*['%Vd1Š1p[iYoR[ ] |gP_KܔfU%m,to/-WKNۊ(ljw|c_6_Z*pGEJ>\/Lr9\1$8W8}(>%}aZGPt{&k﷨٥fCy.&k|a;έZ9$ϥ?]W-%ḤLjK+SRA螾Υ q'ee۩LګQ`wMSFoz(8fk}Cx_9M(F:7G"*/P;՞ ٍ" )O6O[S|PilsE PkZx5&!kʠ琐xOy;뀄t5y j11E8_&/·C#2D0nI 6X8Dޓʹa X'mG|>m8I7&xg뼎 ?1-}z R!oi_׏#m;yۙM1 Q 6[ aLe9m'PS8{ }uT9*$O"SᏩ9b5 wuhVE598k**iDQq XU v@` X@2'SԜ`$1ZT1XMxX ~ X`Z4$``3C9ZPzC|]H $5,_5H0)>UXղz H ߈$,gRoBr4 AQ-T9IO,#j2|W;I X |~' h\FQ8\d@Q~n$ )~Db-:dxX *[,|Ia qYr ?IU\  m'6 Y $h*`d @-7zMnF+ߖ:z}$ׯ`\~_6d,WXZ^%mI1,5&m^h6Ja9W`|: 4Q߷x}y汻T.xEjL|ҦlzxTEpC#ڣ*[<">KtВV`VoE,x?  xYTST7 Շ:zT㥍ioCUc<85;G{vʎгxUs vNL v_ z1[gz48*zخqtaxX0^!XgQ~l)ȍ1\b[ųh 'V')L-AjiZT=0,l2*;9tay^ KH'L*oˣWi@,e0*9vhS+Y2WѣV;_Yt%fSHO.XŔ[T8`[Vuxau^ż2bjN`H\~5pC艉d43>՛Tg!ezjy C25zFdӣgL[;s4ilWk e6Ŝ܅Cg9ըp. lN [ 8L:puoz*ϐ QuL-5E AЃGCV :MiʢiQ! ?Gnr+L E9 $ݘi7O%!AzjNXE7 ,`٤l[u`V-9`6Ri ls0 ߑblezX+$Ѧl~k^LɸbʭCl0^#3*G;smJrؐxqrOzSkNL#ۊ8^5#õIҔ.qKߎ!di1!*p=)׉, V 9h\(A/IhCLΒ\bn{;I͜2Z`tok(PPLq6Fn;:J,nk򝯣 oӢ͚`.=iy3fr&~udKP:36zØ{;zCxV%3vGG:bh2ͩ YՈ@k=e-]:{,Vl6F]e)dMvۆՔZv,$j9 XlÊg, j,T[0j`(cIk4-0oľ#۔v i\Y-gް3pޕE6oƎdi!w Fnj+- 5oέQ)h#v-{l\- kx%#tStmq>,}9Rrx|W|Z NyôyEa%]X-3GLK,ﮫcHE6~cA:F&*}u  kg!.Ϩ[;}4-]N<"yz-og)>Ѵ xBt:%c#U~8Ygi+fѢ̈}G=`#4/-7zH,/Q[H`N-s"O턆*FxP\7aD:{9nbts|NV=E4\r {VЉBLlnMnXb0>Kz=#&Swǔ,b%:osm8Q da6 K,z(X~_.Y\cy%1[ZQ]>ٹQ@5CcwzeѸ82kː- gF*Qi&(3=c|evߘkuz15Q23ZQ@J)L L+7떣j:L.r dK<)U0&-2Т/}oJRDf=ĩB qҏ+s)Os.|`<`Ll&=y>e*LJxfy/?Q"_0~?,?kFCǤDaƧ GT w;}̈́Z`ZNnƮ(nK *g 5wDWQt* !ўG |[ʾI'?![-lgX414ĉ{a_:, o?eң) VB U5`(H+, XED=+-f/`B9Kkz.Na3tfkt/Myͫ`A,%Tsg@NTfmfbÚVm|܃Q[3{͵COkQmG*-N dV@۬鲅*Ԯ8RoF7gTdqi&!'`V0 bd[] kCt#Q+{=f@y!V,PAXVkST:m֔+01бb2-ս_MLÁ`l2YC2R"=Z eq15ޟk|׊g*yH B@yhX1JET,BuxRq10yOǒqqb|5J?@jA uAh@ Y8IGg*]6 uYxC򒢚Bc` |h5ҒOkCv`B Q():6m3ddk byiSK8=Bk,]ح$MO\Z\1ѓ&Z׭ViM4G{ͨ)+Y 7Wh| %Pq+Z0P LĤfPܨP _^U#zU;rBrF^@ M1jf`rĮB=mjFVR aTkQsmi**ԳƯuKwlZ$Y!u\Aj Lz=qT`OՔB9_N˂t,`@RM;,wƎbsz-ٱua{ؒI\/3C 5v{˺9z}Y[T4pYk6f(X.Q3 XlN_Z|뗳t-X W/s-h M;%@` X@`kIg`| IʂM$7 ) XYp1 , !i#VkHDž>d#"iC2@iҎ@r!-Y]`İ,` X,` X,` X` 0+',IENDB`PNG  IHDRdF IDATx]m\U>"߳6GC"J-V)AEPDDwè/+Ƣ$fj[莤؂]'3s<ɓٹ;̽<{mtuK H  H  H j Y꫍Oe,O dVu.p, ]V!mTwqguyYԹH7 Y"%T!B-UT!B!ui, 5|y 4]hYO7.0Ψ͗/WQT"vcqs"q{ƕ_whi2xcBQg?d'W?[B5^v7 }x'/qAb^[6xx7.@kJ-jo .7(8h;k~F#2=oso4~q!o`)**n[-E,y視 @;=9q w abѲbM{M&@Xk]PuwӊK壋"+ҟj'{[zCp|:oqAi 'P]•. B >0B5 =# K1Z:I|_'!<_V}zk$+9&`6 nٸݳCƅ >a EОXYڞu-#K{ҕ`R=qO/ob_|B=̻ZB G,o782ڏ@?N7^fø'4.H?Rgk q/9?!_LG!z`[1AZSH]nl/b;3Nm(H!/k1)Ǣ,#UL'sllc~@_6̬'x=$Tyu_~*o +La˄23PFZe0d+L9WYY]׻(j'P3$SM)]J.v~E . u$"Gy#ְ c]cq32< , 4k_Z[ +vqjkBdt8h@nrwd{C+펄7MWE9meT8Ӽﮩ yv>19W_Flyqql߻焤ì4tW1vAl7hђB7~!/PZ .%P >m ]ں3t*GFaBw$Tq @`[R UT/_҇8wcV# p -"ao U xjGQd-oo!I8`XԨٌQUH.x D Y# q@Au Rcz3< U+Tӯ샒PK(N@( ezp`LMJֹ`CY9 YT! ,ћ%6¢`ZE$TAPAB$TAPAB$TAPAB!O~*VIENDB`PNG  IHDRc9 1cIDATx xlUE湮 lx(v]OJ;}C;"h#`OMDPD!$(> "S^9ku=ԩ1U֗SSY֞V-,,8fT 0 0 0t SBێHx]Ny^ojs۽ۤ# ]ēv}{sB?a魬{߄xo?VY)zxg:vBo;{VJ԰Nho.:ahkޮv+-,}6{S~0zK}wZ,q?%ގb@,\/!&EI)mT$?܈H6ࢎ@HYO@H4owQﻬ{{bvQLpNBR3zrQ'] "gy6-@b>ᢑFD^y݊g0rrO5{}A*y{՞mMp\h4؝~b?s<2?Y0h>˜kұ<V -PNXwPXx[#ۥ^x:o6 M.P뵎P9E}n|Y? MDqv뀔ˁPFJyk^/,̺h2ۿMB[yM7h6@Ĵj> =wEcrJ˵cmF~B$b^.Z9[Ґ n)tsɲ2浯h񾶧H%@'##>Ic.+Zj!iA6E}XiNi/s2ob_j}jO$ mBJVr/hs;~oU2$mnRIſ.KP㪏ӗy{ qgsD.W!I%@+&&(Pԓr¿z },]B" >m/=dRyzt#?l*RH8󟣑Z]0Ȭ[\4FE),dp WWCZRQ,VFpQGkǺ܌|J,dٌ>O{-uV2+x{ne8E 9dۈ˪,7=(<ƎZ_[g9LznUahO d۫;-^XZ/i,h4j2!Ķ3?2˒Ǒz,anFœ~SQG*# ЕH*|```xtt{f/;_f>h iTC.Ns ~܏GS8E<&4,=qd Yݣ7ߜ:ؕ}v=Nb'-ueN_R_7ÆelyCOr[|Ffޑq[H}խXs,3o pMC[p+3=jW" KO#ɚ>P] qcOr^Ǣ8dS:CFtlE{"|CVxa{A`9z|^0*9w} \Cl=o1v۵ds;ʞW_.袍FDpWJ=Xw!:Uw0QI*G+#[neD"eHZ̓39ލ:][uaIoqoaÆ ;b_e.mW# ЩCg}܅^!ܮ~IzwlM'_qBv=.@&+)Otxℴ?-nx޻umaB5jj,=Z-Y0qԧvK0ł⼃zysfm֭[:([,GW|n0@-,l [a8`qo~ynEa '|}ݗn׍Ђk! }bp뭷}6T*-F }t*^pXrRG8 ^ٹ\Vw|54N(l#DZ}@?EsGAV9~byJV}79CY{ekddj6s~FU5ggKavwSUM妌5ǿ@bCTWSxH3 ͍ތP+21@v 7#Xv(U0׻a?mfԊ |fs/o0ȼ4\DᵒH%@+*h YCPE 0@+kZi3ͪv =j/y{u{4e`?cPE U ol(1@#䶷z{K!2))TY̺hH2YߠˆN)ɺIK9]>B̻}7EnuKb}=弝JB>yOݶ<hoqnvj 477IO+mg~z9DA|ޞq\%^k}- 4.2;*řUD߽IXԒ} (IL%>.M.&>ޛuò Y.}xFenD I\J=~g+ή-d~V9j( ,>hOvً]墎UؔOj3"VT4o{{ˢosv5>d%:~ D ,>9oxz!2DAxVaf!'yUG%Hכ<]40'gm*$Xn=ov^sdHXF|I D Rث! 7 -n(1@;r޿y{s˧9OK,Ȩ`D JdoxNU'yF9DARM{ڢD "dETl~F[uFELht+k}~:j--W2>.JVowMz繸 0@?࢕A!e&.{kNF }_8uRH%@;R[/2"FTn`V- בEN' =QT29RU.E>̀J@"XHjHf=xomVz]., W/V0 0 Gf;R;Qoz.UKb@/!ho۹M"14O:?].s Ձ0/! s9ށ@T 0d s|/Ձ0lk:T`'QjsJG6az_w-0ORTGuc3ݤ 19Q@6S +> S}R-D л`( V/ՑRIo=sh"]N1_G.ڌG8T .e# 7! [(Q;`%qx]4Gy9<@ӽTzmT .CƧ](1@o_zE+CzU D v ޾ dΥjnQZ&j%gcZҊh0*Ix DRRH:>}} V!RxY#|iL}|wv:aJb-ݴV{9&c._sPW8Fɨu!}:3U4S^HJTḔ$O* >l|ͼ|AxTʞ90NRZלDI8g PSOdDOт\s&%=G_Lv%o/3⥎m9;1$C}DS,kR*gm 6!*͘{PhqhyV`LiĢ" {m*~Ha"IVa+]u~(H`D[)Z<Ӓ:qҨ(&1W=5((&#Bp뵼}=\7b _ɖʂuo:#t$H'>5aJ\!T n~* E%M ~0vq?"eֱ66,B[}g5{?])\0s.;!pW{O`?MTǵ5^pKc̹MGa}?tN:_!=kR|[/2%=-.u,oOYhk4^a%hkPY |3d)}9ge"4@!wKCbWP}.᳕@Lѯ$gBڊ4Rk;ogϨQi*plʼn0@A'Ȭ*0xҥOb*tڔZkcQʈ9o$& 9ǸK_(g"1dRk罽O69ގ~~_~Av7Jڔ]3oKniHHZcL)C2Χ9>u-#&zn]ʘM+ea(Vynh{;^ezM_ǖ h~EoWe/qQEFI" +0k8VOZiQq1zHV8hLrN=K~2}hV-T'kÄqb g6oZ:8jصHij)>"% AywkKO6yuJrSDz08t%1*zm鸭w1VNMb[@ WFzU2g.֗&C~#頫}^s;> (cH%mIH-\6չU!,3avrWR⾘5k)?C<:e>AXs9 #(b- rIniESmz;-TE;[>)uFTiMբ~]-)ZVrKB1Pz'Iv)H&CZʾC`MZ5D 4,iѸQWE}c]ݵ3MgZeV|9|޹Ȯt1ma@.vۨ.ZX"yY-bv`.s,]@ LnyM. |XȒypzzUD ɞ.&+G A@ 0 0@qxUa"Q Dz@ @<߱!˒CU У0:RDV;^#+p[X[tz*4E-7RIa~Yz]%Mmy&ݫ-m=1@p]{F˴<vU9!Ժ+Ѯ=?Ǩ~tgFSZC/b6elws:|.FBI{M7Rb) &5}b+x[o} *sR e t ){ ,Ϡ2j9e}mtBьƮlzvF̤\kۤy?zZsܣ 8kw*ϴJni7bBntɄ N[4 " X+Y;cd`#*dx`=+ }ymM'.&3ZWI)r0Y0y}9 LHgԃfbIJ+FXs)8gaq. M.IL_GQI51"+54j,khHe֑<ڀcb1)3#Tͨ=60>ݙ&牏l #&JU?sh0yN3K7V-'s̋(녿]۠1dݎ \i3hJ߯\_|ٌ Cz Pb ]BCg&D?x?DƐB°r*y9bYńzr3>kp)u i0鲗(^A1xǝy t%*CU͵S69aPo¸&TlYks&p2}2V^O4]Zf;c{(J -tx V1皗`<& 8-)d]J[b4k1rQG:-i4kbxF Yߠ?9j9g>̦DNıe8 3R6cn ^Ih9[C tK^ɦTyzTX?!()|VE1E gAhBGtBgޗcp،M1p037)5zWw Й?w‡SZg2rvDS`6QaV\%=5(- MχG5C]G* c5stD%D s϶?Icp|abrN~0ǡ pMv(ni0gMB%-O%0Gb[{[2c^HX^V.OXCG<@Ӭ=RL%ٔj0fվJV{9g@g C^2S+ Xw1?%-bh>*}"vݢyӧ2вFSΝ{%D*u6X% u7QChŇ=?Ue\4'5YN{E\2Kc%MC;+&McbNv9֥N#[c!K4ÞApjHBr.}{O"<;^ Y -Ć'Z\&,ɻBnvs):  wKf:PftekVpUVXC&knuR,aV5wsjamvZvw{\ms[ϓ]ǩQE-+P4 ZJfT 0 0 0 0 00+Lv{-`Xv~^;XM=۩٠ET # Ңۃos AV{;Gmh ]6oOMf۰˽AuO-rQÎT A(*lw u0\@a@a@Vs*r^2+ͩj?'Vw1mۚsG(r7qS erhT΂~EsJAΫG|} @y՟yhYyl"YAnnV{$rv?h>?*W%~ȶfs'b Me# wu2L%uD+5>Ww\{nE zYр xz[)1".Auۢ-ÚRgo[yqn9[W(-YuqasE4p*jA@֚H{ƾب""RI!1t^kNsꡣ5D S1_MJfHBbKz,GqZeBW04vbHعϸ ٨>˔^J{3ڢIi_qOŮ7w&%S1O~_c[۟4gifѼwJeE]TAؙ0sq*&^[<rBU(]bNPRVQX } xOh.Ҧa-l"J_)WsǮX&Ȯh5*In"<\#Y}0^H%U`sIv*6qU,aNl<.aм~!S"uKygsgDDkېtFJ8d"c!ME=SEb;z%=NYurJ,yJ͡lJ0 Dpl?_].CZD1Y1)Av%7Xl7#ْb (ENOG'|3Zauȡ'(|J46?bs7>0QHCwiǼѬeV`ÞM 2ZIQc~ĺjfD*"2kJ!H0S6!rI:[WgĹq'-V󏋆}/D.eZui0t saog.Lu%g(jDU ]{I++&eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3 cHRMz%u0`:o_F`IDATxbHl0yTf4~~BGyD;?:?_vD?ww$+_h"<]'r.(GIENDB`PNG  IHDR!V\D pHYs   MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3 cHRMz%u0`:o_F^IDATxұ Pпj6`&8 jbu׿ Y#lf-f6ݭW=]UN ݜ"""a 1E,Cs`PIENDB`PNG  IHDR2#YIDATxb<~8,@laa1t &A F5Qg: oqJ8 'N!y;Tvv@|~-)@]9΂fVv[Aig7=:=8}~΂nA UK|aHMIvF` RÕ ΂XIţ8)%"m:kY9' U9!IENDB`PNG  IHDR2#YIDATxby&,@,''7#&A F5Qg: oqJ'~ Df6v@|~ԝbq@]9΂fVv[Aig76?0߸To [PB3&$Oia0 5\,d[<8ZR,R+騳F5ꬑS?zh9 9HIENDB`PNG  IHDR2#YIDATxb<~8,@=tU&A F5Qg: oqJ)'^)+Q8f6v@|~ԃ"1@]9΂fVv[Aig7<߸T [PB3&$Oia0 5\,d[<8ZR,R+騳F5ꬑS_zu9 9z JIENDB`PNG  IHDR2#YIDATxb<~8,@laa1t &A F5Qg: oqJxR8, 8Ie&HD;@dpR'iw HbA@@| 4ÀT\xٍ0(QqX%1,3rD?,b 6 .zqzA6 Bσ + X@䜣d&/IB" d ԙIENDB`PNG  IHDRaIDATxbb0ˁh fXH Y Kx-$ \@\l@WbqWCVL p 0d?#Cs vp"o"BF s0t@qB5Q=Ͱ)'cv{hIENDB`PNG  IHDRaIDATxb?%D 3gd`"` ,.L dsQ Un?/W@ gPd'1hIB6 7"7q@|;7 bQ;4@ OH@pf"bH}dl8>4a Tvd&14 5@܋l PD ^&t ɀꁇ,l u@|* jP`G ܈@8}8-  77B:IENDB`PNG  IHDRa*IDATxڤ=HAq5=A "lMDͽ%Hzii5VAQ!|KŃ?adS?'(cV{9)bW("aXG v V0q:PQ+[kn%Hf\]:qc!R3W;<Sؑ'T]깅5qK= !s~Bؓs2,FԜyq@^+ ռw̡OPCBvm;R-:<`LrKXӯMz;D2IENDB`PNG  IHDR #= pHYs   MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3 cHRMz%u0`:o_FeVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3 cHRMz%u0`:o_FIDATx[0ᯈ(/Ν(B}& 7^i?L;Gpr os~RΘ 4aN1a;t8IE}ڪ w F~-\lQ0K7LkUgNJʵzӚmszUʊ*..IENDB`PNG  IHDR pHYs   MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3 cHRMz%u0`:o_FIDATx[ 0 EO$neW30f~RJeopmT̨V|–mxID[30,]]} Q`}t68^ du'/yy;S3 wjILbѴIENDB`PNG  IHDR k pHYs   MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3 cHRMz%u0`:o_F3IDATx˱ #$"*D  cEL ?7A7R8IENDB`PNG  IHDR k pHYs   MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3 cHRMz%u0`:o_F4IDATxb"+#o ?~31PF5 W$IENDB`PNG  IHDR 7 pHYs   MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3 cHRMz%u0`:o_F0IDATxbda``b 000OB7z ,/qIENDB`PNG  IHDR v4A pHYs   MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3 cHRMz%u0`:o_FeIDATxڤ C?v'z%K4%"M6hv6L"A\[{\My5ɝ}l9u8NSSqVB9IENDB`PNG  IHDR v4A pHYs   MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3 cHRMz%u0`:o_FoIDATxڜ[ 'i?nMH},!:UQeZ4Ux}/=l!6Ie)JSv3t ;BmcUFޅQ 2LlIENDB`PNG  IHDRa pHYs   cHRMz%u0`:o_FIDATxڤ1 @E_3XYDϠ#HS1VKf``bz 4~W1XP7}Lb Ik&y_&y$ Uh>> ہ Ȇ`3$C]Cf"2 d#)p30A (8sIENDB`PNG  IHDRasRGBgAMA a pHYsod IDAT8OSQ@D+ Dq ߽DW%4n߾4۵M62f1DѣC8(rm|f|}-f 4]Nq\%`qM;LFkWpMK]6%Gqz3 aTMM=x|%;fRs$6B"kf6F[H@i#P:%5"E0&X6䣍 e0Z&} IE6lN1JG:IENDB`PNG  IHDRasRGBgAMA a pHYsodIDAT8OSK echbLԺэn@W[/Ry4B̼VqZ5-[Wۣ{2}|$IFpļX#L,HȾN;0 Ő2~GA9]nw;pKLLLtW58:_/jLa/Dɡ"m3X/N@vn,uHˆ.|:(]mtլIm,t$teMc2_4QYڰѵ\8vbIENDB`PNG  IHDR##ٳYsRGBgAMA a pHYsodIDATXG; 0Ds.|*;#x-RG6 @c9B F$EbϺM#)BńlF-[ b=tծ- ;̜ڒѕUpGȶKCR8ih@'r1IENDB`PNG  IHDR##ٳYsRGBgAMA a pHYsodIDATXG= `/Tz5Hf" >W8@zf^'MEBQ.EZ7"r5#,>DE㩻;㩔Qx'h]\٤Py%OPB? f 1LRnD;{lr]1r<D\2 AA# c 4 @d67 d$&pc|2QL@A2_ESIENDB`PNG  IHDR##ٳY pHYsod MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3 cHRMz%u0`:o_FIDATxMj1xw8d!$:H7-tQ8y݄H@\rS0/132Xҋ~|WLUUxf !HR#isvn1 8ۏ8Yu 0y;gJHjU1!)zXmaz 0Z3[uyflṔV]IKI'3Nu]g#u]gI'`m=SJ0) DI!ih_ \011ƧRbσa` `u&eIENDB`PNG  IHDR##ٳY pHYsod MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3 cHRMz%u0`:o_F IDATxMjAqϡg̴ 7Bk .s g&wl&'GoMQ !%IIobfPқ1'IGE̞)R.ЗBqS̶_n4J`s؜_L?U0@-i+Ib}vjdy-g`lTY5m2˲lg 7E&ؘwѶ8a_cx16&C'L$Lœr#IENDB`PNG  IHDR##ٳY pHYsod MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3 cHRMz%u0`:o_F)IDATxOj1cHfLA7.Ac]:N0L [6#QJ)zDLDL|C`$xKW1&>˲gkItoR4CDCsn@DÛ`1#S53*Fk=ZZZk= &"R;疿w-E䝈&byvdqM Gfvac%Cyӂf1h{SgAhcB&zCb- `RQY=ó^!˲X(ng|{CXZ{@el˾ ]:CSn]JMu*L3|DW[5>zWs{Ƙ&Dځie%>([Ǩ *%MW#kIENDB`PNG  IHDR##ٳYsRGBgAMA a pHYsod%IDATXG 0;G=Mi t:nޝ@wp*XAA EhG C!//_/!A$=WZ pxxeL+xtmDQF4iKn:Näi:;\Lbijj}bvD0 7)+Yحch2! tF#jH 2LjxgF< 1TTcreij*. c޿rTC ֟AcY<8kog:7nga;TVIENDB`PNG  IHDR##ٳYsRGBgAMA a pHYsod=IDATXGM P9q"8Z@+}4. y+5Թ𒈌kqιiZAGQTT2$㫄aYͦ \ FNEkI!x@yo'I% Ýycn{<̆,EӶm{Lp =W,͌a!l=h+ s4Mgl h1G290!:o L+(`v$Z;tz{^n렏)="'뀠ʖXEQ;r2#G 8P&e''ŝzIENDB`PNG  IHDR##ٳYsRGBgAMA a pHYsodIDATXGc`!0!0C@GGGJW ,e1=*ʁ Q{GC`4FCj!<hIENDB`PNG  IHDR##ٳYsRGBgAMA a pHYsodIDATXG햽JQMTDSFlR JZX|V,- (>@DPQA Dw9gNf7H>I$a\.JO*D C籚}Ϲ\nL6q(t@8t0 ':a`g1rKT` fmE뗂Wb/\X{CM"~51$G3*Qy7NqT퐺w(β$IsvjNLD?}Jq@*r >2|@4IENDB`PNG  IHDR##ٳYsRGBgAMA a pHYsodAIDATXG햽j0RRt ċ[1!}6C) y,%DV;\%{Y9{[=S9/6(iO뺾:u )MeY3dQO#+ O 4MNJa^aXyͲX4W`f*k-jr({=ttH02 4)1xb AwYaٶA}1汎7I:,qZV&f p\_kIENDB`PNG  IHDR##ٳYsRGBgAMA a pHYsodIDATXG[@ Eߺ]q " MZ0LHbJ=$ 3`> y~MtR ʲl_E'd ER^j!^r`5@}C(tl`J@Нl`M@A fE cLޟI0&qׄ|4[X ] |Z9@$@걦C]aX7ZFhdz̀0m \ג#yIENDB`PNG  IHDR##ٳYsRGBgAMA a pHYsodIDATXG[ E_%@qK[t&CX2@M41==0ԀP7c̡Ƌs4ϼ Tlq1P$rT:O4 Mq<,gG4g ډ6f#9R]aϼ.ARS`i"@]o6 gkO'6A݁8`I8Ǚ6u8HmC7Fj@ 1nG4QIENDB`PNG  IHDR##ٳYsRGBgAMA a pHYsod4IDATXG 0 ;H˔1h}RR9Jy೿VVp$_73I&k)EBh)gLA TE#ZG`Wր( _r,˓D  #<5Ctbr ? r&@ Q0@`c0 7.MN:i@ViYgT P0c cN޳naL{90ì?\R6.4i U\p DgZ&c6rg hs19ў43>>_јIENDB`PNG  IHDR##ٳYsRGBgAMA a pHYsodHIDATXG[0WBZҸnB{MTL!~#ᶴBdCqFL&&}S 3u]ߓ$م,yў?L'QA$*:&,;0!:@4I5 t  @4!+uF|!ހV 5/jILכdLnm۾Z0p o$1п >*I3at \B\Sz 2Ii`ft}j׿yb_ Cb[?;wĄ018L};f(èRIENDB`PNG  IHDR##ٳYsRGBgAMA a pHYsodHIDATXG 0@3xM7ЏOOGĉAjOQIÕ8#fM!@8W6+4 .IENDB`PNG  IHDR##ٳYsRGBgAMA a pHYsodGIDATXGӱ 0@wpT# df>]6 W㌀oqBqI 8 IENDB`PNG  IHDR##ٳYsRGBgAMA a pHYsodwIDATXGc044,a8Qѐ Rsh^iFHH腰R1Hig4 4ClSnhDISwhJ}M2fh掆h{t6fD+SfIENDB`PNG  IHDR##ٳYsRGBgAMA a pHYsodqIDATXG핱 0 54,[ĸs~ B ED0_m6 30s|Ug dT{&SL,&i-=t!3IENDB`PNG  IHDRaIDATxb?%Bc@\^@,/xwCIzOs vb^(*@8!& ` J ʗr';rrr ,Rp ďllq/XI1:ihc ہ8 f<ў;p ` .⽸ EM: Vb6( O&@l+)gR@?Ci)x7Z G% :!ɔIENDB`PNG  IHDRa pHYs   MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3 cHRMz%u0`:o_FVIDATxڄOQ37QY&0d˂[BʊRbF$edb04HCg{=i>v7flf'TAr8'ʴ'8/@V,3:,h(P&E J*-ޖѡضbU(<JDa]em=1 >[Ct.W:-G2sf-2vnHH\Pg (pʺΈ~uĖQ t<ŋs@%5N 35j8#WD$+<WT˩@kfUA 10My5YeV3X`Q˕8CPpzoB%y.pFZdapQ AFQLt`3W18tUg8ԗ`-({>*Qւ -D -!jIENDB`PNG  IHDRa pHYs   MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3 cHRMz%u0`:o_FIIDATxڌK[Q{w4KČ.`(E3fnuڥC ] A suѦ?h8sm J#fƘI~IUeffιWWUsc<﷢syZш]|# dYF$ sdYFZeyyE,cggU@TU$ann5* Ǵm `ccftAyY!j$Ij4 T-DQ-Ipss`0 c<{Fja!s888 Ǣ7z}T*0DD""ƢSynKۥ^BVljB@}P@U ÐxRh{Dx>/~k1v|>|'ZIENDB`

$i18n{message}

$i18n{message}

$i18n{message}

// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Custom binding for the app API. var appNatives = requireNative('app'); var process = requireNative('process'); var extensionId = process.GetExtensionId(); var logActivity = requireNative('activityLogger'); function wrapForLogging(fun) { if (!extensionId) return fun; // nothing interesting to log without an extension return function() { // TODO(ataly): We need to make sure we use the right prototype for // fun.apply. Array slice can either be rewritten or similarly defined. logActivity.LogAPICall(extensionId, "app." + fun.name, $Array.slice(arguments)); return $Function.apply(fun, this, arguments); }; } // This becomes chrome.app var app = { getIsInstalled: wrapForLogging(appNatives.GetIsInstalled), getDetails: wrapForLogging(appNatives.GetDetails), runningState: wrapForLogging(appNatives.GetRunningState) }; // Tricky; "getIsInstalled" is actually exposed as the getter "isInstalled", // but we don't have a way to express this in the schema JSON (nor is it // worth it for this one special case). // // So, define it manually, and let the getIsInstalled function act as its // documentation. var isInstalled = wrapForLogging(appNatives.GetIsInstalled); $Object.defineProperty( app, 'isInstalled', { __proto__: null, configurable: true, enumerable: true, get: function() { return isInstalled(); }, }); // Called by app_bindings.cc. function onInstallStateResponse(state, callbackId) { var callback = callbacks[callbackId]; delete callbacks[callbackId]; if (typeof callback == 'function') { try { callback(state); } catch (e) { console.error('Exception in chrome.app.installState response handler: ' + e.stack); } } } // TODO(kalman): move this stuff to its own custom bindings. var callbacks = { __proto__: null }; var nextCallbackId = 1; function getInstallState(callback) { var callbackId = nextCallbackId++; callbacks[callbackId] = callback; appNatives.GetInstallState(callbackId); } $Object.defineProperty( app, 'installState', { __proto__: null, configurable: true, enumerable: true, value: wrapForLogging(getInstallState), writable: true, }); exports.$set('binding', app); exports.$set('onInstallStateResponse', onInstallStateResponse); // Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Custom bindings for the automation API. var AutomationNode = require('automationNode').AutomationNode; var AutomationRootNode = require('automationNode').AutomationRootNode; var automation = apiBridge || require('binding').Binding.create('automation'); var automationInternal = getInternalApi ? getInternalApi('automationInternal') : require('binding').Binding.create('automationInternal').generate(); var exceptionHandler = require('uncaught_exception_handler'); var logging = requireNative('logging'); var nativeAutomationInternal = requireNative('automationInternal'); var DestroyAccessibilityTree = nativeAutomationInternal.DestroyAccessibilityTree; var GetIntAttribute = nativeAutomationInternal.GetIntAttribute; var StartCachingAccessibilityTrees = nativeAutomationInternal.StartCachingAccessibilityTrees; var AddTreeChangeObserver = nativeAutomationInternal.AddTreeChangeObserver; var RemoveTreeChangeObserver = nativeAutomationInternal.RemoveTreeChangeObserver; var GetFocusNative = nativeAutomationInternal.GetFocus; var jsLastError = bindingUtil ? undefined : require('lastError'); function hasLastError() { return bindingUtil ? bindingUtil.hasLastError() : jsLastError.hasError(chrome); } /** * A namespace to export utility functions to other files in automation. */ window.automationUtil = function() {}; // TODO(aboxhall): Look into using WeakMap var idToCallback = {}; var DESKTOP_TREE_ID = 0; automationUtil.storeTreeCallback = function(id, callback) { if (!callback) return; var targetTree = AutomationRootNode.get(id); if (!targetTree) { // If we haven't cached the tree, hold the callback until the tree is // populated by the initial onAccessibilityEvent call. if (id in idToCallback) idToCallback[id].push(callback); else idToCallback[id] = [callback]; } else { callback(targetTree); } }; /** * Global list of tree change observers. * @type {Object} */ automationUtil.treeChangeObserverMap = {}; /** * The id of the next tree change observer. * @type {number} */ automationUtil.nextTreeChangeObserverId = 1; /** * @type {AutomationNode} The current focused node. This is only updated * when calling automationUtil.updateFocusedNode. */ automationUtil.focusedNode = null; /** * Gets the currently focused AutomationNode. * @return {AutomationNode} */ automationUtil.getFocus = function() { var focusedNodeInfo = GetFocusNative(DESKTOP_TREE_ID); if (!focusedNodeInfo) return null; var tree = AutomationRootNode.getOrCreate(focusedNodeInfo.treeId); if (tree) return privates(tree).impl.get(focusedNodeInfo.nodeId); }; /** * Update automationUtil.focusedNode to be the node that currently has focus. */ automationUtil.updateFocusedNode = function() { automationUtil.focusedNode = automationUtil.getFocus(); }; /** * Updates the focus on blur. */ automationUtil.updateFocusedNodeOnBlur = function() { var focus = automationUtil.getFocus(); automationUtil.focusedNode = focus ? focus.root : null; }; automation.registerCustomHook(function(bindingsAPI) { var apiFunctions = bindingsAPI.apiFunctions; // TODO(aboxhall, dtseng): Make this return the speced AutomationRootNode obj. apiFunctions.setHandleRequest('getTree', function getTree(tabID, callback) { StartCachingAccessibilityTrees(); // enableTab() ensures the renderer for the active or specified tab has // accessibility enabled, and fetches its ax tree id to use as // a key in the idToAutomationRootNode map. The callback to // enableTab is bound to the callback passed in to getTree(), so that once // the tree is available (either due to having been cached earlier, or after // an accessibility event occurs which causes the tree to be populated), the // callback can be called. var params = { tabID: tabID }; automationInternal.enableTab(params, function onEnable(id) { if (hasLastError()) { callback(); return; } automationUtil.storeTreeCallback(id, callback); }); }); var desktopTree = null; apiFunctions.setHandleRequest('getDesktop', function(callback) { StartCachingAccessibilityTrees(); desktopTree = AutomationRootNode.get(DESKTOP_TREE_ID); if (!desktopTree) { if (DESKTOP_TREE_ID in idToCallback) idToCallback[DESKTOP_TREE_ID].push(callback); else idToCallback[DESKTOP_TREE_ID] = [callback]; // TODO(dtseng): Disable desktop tree once desktop object goes out of // scope. automationInternal.enableDesktop(function() { if (hasLastError()) { AutomationRootNode.destroy(DESKTOP_TREE_ID); callback(); return; } }); } else { callback(desktopTree); } }); apiFunctions.setHandleRequest('getFocus', function(callback) { callback(automationUtil.getFocus()); }); function removeTreeChangeObserver(observer) { for (var id in automationUtil.treeChangeObserverMap) { if (automationUtil.treeChangeObserverMap[id] == observer) { RemoveTreeChangeObserver(id); delete automationUtil.treeChangeObserverMap[id]; return; } } } apiFunctions.setHandleRequest('removeTreeChangeObserver', function(observer) { removeTreeChangeObserver(observer); }); function addTreeChangeObserver(filter, observer) { removeTreeChangeObserver(observer); var id = automationUtil.nextTreeChangeObserverId++; AddTreeChangeObserver(id, filter); automationUtil.treeChangeObserverMap[id] = observer; } apiFunctions.setHandleRequest('addTreeChangeObserver', function(filter, observer) { addTreeChangeObserver(filter, observer); }); apiFunctions.setHandleRequest('setDocumentSelection', function(params) { var anchorNodeImpl = privates(params.anchorObject).impl; var focusNodeImpl = privates(params.focusObject).impl; if (anchorNodeImpl.treeID !== focusNodeImpl.treeID) throw new Error('Selection anchor and focus must be in the same tree.'); if (anchorNodeImpl.treeID === DESKTOP_TREE_ID) { throw new Error('Use AutomationNode.setSelection to set the selection ' + 'in the desktop tree.'); } automationInternal.performAction({ treeID: anchorNodeImpl.treeID, automationNodeID: anchorNodeImpl.id, actionType: 'setSelection'}, { focusNodeID: focusNodeImpl.id, anchorOffset: params.anchorOffset, focusOffset: params.focusOffset }); }); }); automationInternal.onChildTreeID.addListener(function(treeID, nodeID) { var tree = AutomationRootNode.getOrCreate(treeID); if (!tree) return; var node = privates(tree).impl.get(nodeID); if (!node) return; // A WebView in the desktop tree has a different AX tree as its child. // When we encounter a WebView with a child AX tree id that we don't // currently have cached, explicitly request that AX tree from the // browser process and set up a callback when it loads to attach that // tree as a child of this node and fire appropriate events. var childTreeID = GetIntAttribute(treeID, nodeID, 'childTreeId'); if (!childTreeID) return; var subroot = AutomationRootNode.get(childTreeID); if (!subroot || subroot.role == 'unknown') { automationUtil.storeTreeCallback(childTreeID, function(root) { // Return early if the root has already been attached. if (root.parent) return; privates(root).impl.setHostNode(node); if (root.docLoaded) { privates(root).impl.dispatchEvent('loadComplete', 'page'); } privates(node).impl.dispatchEvent('childrenChanged', 'none'); }); automationInternal.enableFrame(childTreeID); } else { privates(subroot).impl.setHostNode(node); } }); automationInternal.onTreeChange.addListener(function(observerID, treeID, nodeID, changeType) { var tree = AutomationRootNode.getOrCreate(treeID); if (!tree) return; var node = privates(tree).impl.get(nodeID); if (!node) return; var observer = automationUtil.treeChangeObserverMap[observerID]; if (!observer) return; try { observer({target: node, type: changeType}); } catch (e) { exceptionHandler.handle('Error in tree change observer for ' + treeChange.type, e); } }); automationInternal.onNodesRemoved.addListener(function(treeID, nodeIDs) { var tree = AutomationRootNode.getOrCreate(treeID); if (!tree) return; for (var i = 0; i < nodeIDs.length; i++) { privates(tree).impl.remove(nodeIDs[i]); } }); /** * Dispatch accessibility events fired on individual nodes to its * corresponding AutomationNode. Handle focus events specially * (see below). */ automationInternal.onAccessibilityEvent.addListener(function(eventParams) { var id = eventParams.treeID; var targetTree = AutomationRootNode.getOrCreate(id); if (eventParams.eventType == 'blur') { // Work around an issue where Chrome sends us 'blur' events on the // root node when nothing has focus, we need to treat those as focus // events but otherwise not handle blur events specially. var node = privates(targetTree).impl.get(eventParams.targetID); if (node == node.root) automationUtil.updateFocusedNodeOnBlur(); } else if (eventParams.eventType == 'mediaStartedPlaying' || eventParams.eventType == 'mediaStoppedPlaying') { // These events are global to the tree. eventParams.targetID = privates(targetTree).impl.id; } else { var previousFocusedNode = automationUtil.focusedNode; automationUtil.updateFocusedNode(); // Fire focus events if necessary. if (automationUtil.focusedNode && automationUtil.focusedNode != previousFocusedNode) { var eventParamsCopy = {}; for (var key in eventParams) eventParamsCopy[key] = eventParams[key]; eventParamsCopy['eventType'] = 'focus'; eventParamsCopy['treeID'] = privates(automationUtil.focusedNode.root).impl.treeID; eventParamsCopy['targetID'] = privates(automationUtil.focusedNode).impl.id; privates(automationUtil.focusedNode.root) .impl.onAccessibilityEvent(eventParamsCopy); } } // Note that focus type events have already been handled above if there was a // focused node. All other events, even non-focus events that triggered a // focus dispatch, still need to have their original event fired. if ((!automationUtil.focusedNode || eventParams.eventType != 'focus') && !privates(targetTree).impl.onAccessibilityEvent(eventParams)) return; // If we're not waiting on a callback to getTree(), we can early out here. if (!(id in idToCallback)) return; // We usually get a 'placeholder' tree first, which doesn't have any url // attribute or child nodes. If we've got that, wait for the full tree before // calling the callback. // TODO(dmazzoni): Don't send down placeholder (crbug.com/397553) if (id != DESKTOP_TREE_ID && !targetTree.url && targetTree.children.length == 0) return; // If the tree wasn't available when getTree() was called, the callback will // have been cached in idToCallback, so call and delete it now that we // have the complete tree. for (var i = 0; i < idToCallback[id].length; i++) { var callback = idToCallback[id][i]; callback(targetTree); } delete idToCallback[id]; }); automationInternal.onAccessibilityTreeDestroyed.addListener(function(id) { // Destroy the AutomationRootNode. var targetTree = AutomationRootNode.get(id); if (targetTree) { privates(targetTree).impl.destroy(); AutomationRootNode.destroy(id); } else { logging.WARNING('no targetTree to destroy'); } // Destroy the native cache of the accessibility tree. DestroyAccessibilityTree(id); }); automationInternal.onAccessibilityTreeSerializationError.addListener( function(id) { automationInternal.enableFrame(id); }); automationInternal.onActionResult.addListener( function(treeID, requestID, result) { var targetTree = AutomationRootNode.get(treeID); if (!targetTree) return; privates(targetTree).impl.onActionResult(requestID, result); }); if (!apiBridge) exports.$set('binding', automation.generate()); // Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. var utils = require('utils'); function AutomationEventImpl(type, target, eventFrom) { this.propagationStopped = false; this.type = type; this.target = target; this.eventPhase = Event.NONE; this.eventFrom = eventFrom; } AutomationEventImpl.prototype = { __proto__: null, stopPropagation: function() { this.propagationStopped = true; }, }; function AutomationEvent() { privates(AutomationEvent).constructPrivate(this, arguments); } utils.expose(AutomationEvent, AutomationEventImpl, { functions: [ 'stopPropagation', ], readonly: [ 'type', 'target', 'eventPhase', 'eventFrom', ], }); exports.$set('AutomationEvent', AutomationEvent); // Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. var AutomationEvent = require('automationEvent').AutomationEvent; var automationInternal = getInternalApi ? getInternalApi('automationInternal') : require('binding').Binding.create('automationInternal').generate(); var exceptionHandler = require('uncaught_exception_handler'); var natives = requireNative('automationInternal'); var IsInteractPermitted = natives.IsInteractPermitted; /** * @param {number} axTreeID The id of the accessibility tree. * @return {?number} The id of the root node. */ var GetRootID = natives.GetRootID; /** * @param {number} axTreeID The id of the accessibility tree. * @return {?string} The title of the document. */ var GetDocTitle = natives.GetDocTitle; /** * @param {number} axTreeID The id of the accessibility tree. * @return {?string} The url of the document. */ var GetDocURL = natives.GetDocURL; /** * @param {number} axTreeID The id of the accessibility tree. * @return {?boolean} True if the document has finished loading. */ var GetDocLoaded = natives.GetDocLoaded; /** * @param {number} axTreeID The id of the accessibility tree. * @return {?number} The loading progress, from 0.0 to 1.0 (fully loaded). */ var GetDocLoadingProgress = natives.GetDocLoadingProgress; /** * @param {number} axTreeID The id of the accessibility tree. * @return {?number} The ID of the selection anchor object. */ var GetAnchorObjectID = natives.GetAnchorObjectID; /** * @param {number} axTreeID The id of the accessibility tree. * @return {?number} The selection anchor offset. */ var GetAnchorOffset = natives.GetAnchorOffset; /** * @param {number} axTreeID The id of the accessibility tree. * @return {?string} The selection anchor affinity. */ var GetAnchorAffinity = natives.GetAnchorAffinity; /** * @param {number} axTreeID The id of the accessibility tree. * @return {?number} The ID of the selection focus object. */ var GetFocusObjectID = natives.GetFocusObjectID; /** * @param {number} axTreeID The id of the accessibility tree. * @return {?number} The selection focus offset. */ var GetFocusOffset = natives.GetFocusOffset; /** * @param {number} axTreeID The id of the accessibility tree. * @return {?string} The selection focus affinity. */ var GetFocusAffinity = natives.GetFocusAffinity; /** * @param {number} axTreeID The id of the accessibility tree. * @param {number} nodeID The id of a node. * @return {?number} The id of the node's parent, or undefined if it's the * root of its tree or if the tree or node wasn't found. */ var GetParentID = natives.GetParentID; /** * @param {number} axTreeID The id of the accessibility tree. * @param {number} nodeID The id of a node. * @return {?number} The number of children of the node, or undefined if * the tree or node wasn't found. */ var GetChildCount = natives.GetChildCount; /** * @param {number} axTreeID The id of the accessibility tree. * @param {number} nodeID The id of a node. * @param {number} childIndex An index of a child of this node. * @return {?number} The id of the child at the given index, or undefined * if the tree or node or child at that index wasn't found. */ var GetChildIDAtIndex = natives.GetChildIDAtIndex; /** * @param {number} axTreeID The id of the accessibility tree. * @param {number} nodeID The id of a node. * @return {?number} The ids of the children of the node, or undefined * if the tree or node wasn't found. */ var GetChildIds = natives.GetChildIDs; /** * @param {number} axTreeID The id of the accessibility tree. * @param {number} nodeID The id of a node. * @return {?Object} An object mapping html attributes to values. */ var GetHtmlAttributes = natives.GetHtmlAttributes; /** * @param {number} axTreeID The id of the accessibility tree. * @param {number} nodeID The id of a node. * @return {?number} The index of this node in its parent, or undefined if * the tree or node or node parent wasn't found. */ var GetIndexInParent = natives.GetIndexInParent; /** * @param {number} axTreeID The id of the accessibility tree. * @param {number} nodeID The id of a node. * @return {?Object} An object with a string key for every state flag set, * or undefined if the tree or node or node parent wasn't found. */ var GetState = natives.GetState; /** * @param {number} axTreeID The id of the accessibility tree. * @param {number} nodeID The id of a node. * @return {string} The restriction, one of * "disabled", "readOnly" or undefined if enabled or other object not disabled */ var GetRestriction = natives.GetRestriction; /** * @param {number} axTreeID The id of the accessibility tree. * @param {number} nodeID The id of a node. * @return {string} The checked state, as undefined, "true", "false" or "mixed". */ var GetChecked = natives.GetChecked; /** * @param {number} axTreeID The id of the accessibility tree. * @param {number} nodeID The id of a node. * @return {string} The role of the node, or undefined if the tree or * node wasn't found. */ var GetRole = natives.GetRole; /** * @param {number} axTreeID The id of the accessibility tree. * @param {number} nodeID The id of a node. * @return {?automation.Rect} The location of the node, or undefined if * the tree or node wasn't found. */ var GetLocation = natives.GetLocation; /** * @param {number} axTreeID The id of the accessibility tree. * @param {number} nodeID The id of a node. * @param {number} startIndex The start index of the range. * @param {number} endIndex The end index of the range. * @return {?automation.Rect} The bounding box of the subrange of this node, * or the location if there are no subranges, or undefined if * the tree or node wasn't found. */ var GetBoundsForRange = natives.GetBoundsForRange; /** * @param {number} axTreeID The id of the accessibility tree. * @param {number} nodeID The id of a node. * @return {?automation.Rect} The unclipped location of the node, or * undefined if the tree or node wasn't found. */ var GetUnclippedLocation = natives.GetUnclippedLocation; /** * @param {number} axTreeID The id of the accessibility tree. * @param {number} nodeID The id of a node. * @return {!Array.} The text offset where each line starts, or an empty * array if this node has no text content, or undefined if the tree or node * was not found. */ var GetLineStartOffsets = requireNative( 'automationInternal').GetLineStartOffsets; /** * @param {number} axTreeID The id of the accessibility tree. * @param {number} nodeID The id of a node. * @param {string} attr The name of a string attribute. * @return {?string} The value of this attribute, or undefined if the tree, * node, or attribute wasn't found. */ var GetStringAttribute = natives.GetStringAttribute; /** * @param {number} axTreeID The id of the accessibility tree. * @param {number} nodeID The id of a node. * @param {string} attr The name of an attribute. * @return {?boolean} The value of this attribute, or undefined if the tree, * node, or attribute wasn't found. */ var GetBoolAttribute = natives.GetBoolAttribute; /** * @param {number} axTreeID The id of the accessibility tree. * @param {number} nodeID The id of a node. * @param {string} attr The name of an attribute. * @return {?number} The value of this attribute, or undefined if the tree, * node, or attribute wasn't found. */ var GetIntAttribute = natives.GetIntAttribute; /** * @param {number} axTreeID The id of the accessibility tree. * @param {number} nodeID The id of a node. * @param {string} attr The name of an attribute. * @return {?number} The value of this attribute, or undefined if the tree, * node, or attribute wasn't found. */ var GetFloatAttribute = natives.GetFloatAttribute; /** * @param {number} axTreeID The id of the accessibility tree. * @param {number} nodeID The id of a node. * @param {string} attr The name of an attribute. * @return {?Array.} The value of this attribute, or undefined * if the tree, node, or attribute wasn't found. */ var GetIntListAttribute = natives.GetIntListAttribute; /** * @param {number} axTreeID The id of the accessibility tree. * @param {number} nodeID The id of a node. * @param {string} attr The name of an HTML attribute. * @return {?string} The value of this attribute, or undefined if the tree, * node, or attribute wasn't found. */ var GetHtmlAttribute = natives.GetHtmlAttribute; /** * @param {number} axTreeID The id of the accessibility tree. * @param {number} nodeID The id of a node. * @return {automation.NameFromType} The source of the node's name. */ var GetNameFrom = natives.GetNameFrom; /** * @param {number} axTreeID The id of the accessibility tree. * @param {number} nodeID The id of a node. * @return {boolean} */ var GetBold = natives.GetBold; /** * @param {number} axTreeID The id of the accessibility tree. * @param {number} nodeID The id of a node. * @return {boolean} */ var GetItalic = natives.GetItalic; /** * @param {number} axTreeID The id of the accessibility tree. * @param {number} nodeID The id of a node. * @return {boolean} */ var GetUnderline = natives.GetUnderline; /** * @param {number} axTreeID The id of the accessibility tree. * @param {number} nodeID The id of a node. * @return {boolean} */ var GetLineThrough = natives.GetLineThrough; /** * @param {number} axTreeID The id of the accessibility tree. * @param {number} nodeID The id of a node. * @return {?Array.} List of custom actions of the * node. */ var GetCustomActions = natives.GetCustomActions; var logging = requireNative('logging'); var utils = require('utils'); /** * A single node in the Automation tree. * @param {AutomationRootNodeImpl} root The root of the tree. * @constructor */ function AutomationNodeImpl(root) { this.rootImpl = root; this.hostNode_ = null; this.listeners = {__proto__: null}; } AutomationNodeImpl.prototype = { __proto__: null, treeID: -1, id: -1, isRootNode: false, detach: function() { this.rootImpl = null; this.hostNode_ = null; this.listeners = {__proto__: null}; }, get root() { return this.rootImpl && this.rootImpl.wrapper; }, get parent() { if (!this.rootImpl) return undefined; if (this.hostNode_) return this.hostNode_; var parentID = GetParentID(this.treeID, this.id); return this.rootImpl.get(parentID); }, get htmlAttributes() { return GetHtmlAttributes(this.treeID, this.id) || {}; }, get state() { return GetState(this.treeID, this.id) || {}; }, get role() { return GetRole(this.treeID, this.id); }, get restriction() { return GetRestriction(this.treeID, this.id); }, get checked() { return GetChecked(this.treeID, this.id); }, get location() { return GetLocation(this.treeID, this.id); }, boundsForRange: function(startIndex, endIndex) { return GetBoundsForRange(this.treeID, this.id, startIndex, endIndex); }, get unclippedLocation() { var result = GetUnclippedLocation(this.treeID, this.id); if (result === undefined) result = GetLocation(this.treeID, this.id); return result; }, get indexInParent() { return GetIndexInParent(this.treeID, this.id); }, get lineStartOffsets() { return GetLineStartOffsets(this.treeID, this.id); }, get childTree() { var childTreeID = GetIntAttribute(this.treeID, this.id, 'childTreeId'); if (childTreeID) return AutomationRootNodeImpl.get(childTreeID); }, get firstChild() { if (!this.rootImpl) return undefined; if (this.childTree) return this.childTree; if (!GetChildCount(this.treeID, this.id)) return undefined; var firstChildID = GetChildIDAtIndex(this.treeID, this.id, 0); return this.rootImpl.get(firstChildID); }, get lastChild() { if (!this.rootImpl) return undefined; if (this.childTree) return this.childTree; var count = GetChildCount(this.treeID, this.id); if (!count) return undefined; var lastChildID = GetChildIDAtIndex(this.treeID, this.id, count - 1); return this.rootImpl.get(lastChildID); }, get children() { if (!this.rootImpl) return []; if (this.childTree) return [this.childTree]; var children = []; var childIds = GetChildIds(this.treeID, this.id); for (var i = 0; i < childIds.length; ++i) { var childID = childIds[i]; var child = this.rootImpl.get(childID); $Array.push(children, child); } return children; }, get previousSibling() { var parent = this.parent; if (!parent) return undefined; parent = privates(parent).impl; var indexInParent = GetIndexInParent(this.treeID, this.id); return this.rootImpl.get( GetChildIDAtIndex(parent.treeID, parent.id, indexInParent - 1)); }, get nextSibling() { var parent = this.parent; if (!parent) return undefined; parent = privates(parent).impl; var indexInParent = GetIndexInParent(this.treeID, this.id); return this.rootImpl.get( GetChildIDAtIndex(parent.treeID, parent.id, indexInParent + 1)); }, get nameFrom() { return GetNameFrom(this.treeID, this.id); }, get bold() { return GetBold(this.treeID, this.id); }, get italic() { return GetItalic(this.treeID, this.id); }, get underline() { return GetUnderline(this.treeID, this.id); }, get lineThrough() { return GetLineThrough(this.treeID, this.id); }, get customActions() { return GetCustomActions(this.treeID, this.id); }, doDefault: function() { this.performAction_('doDefault'); }, focus: function() { this.performAction_('focus'); }, getImageData: function(maxWidth, maxHeight) { this.performAction_('getImageData', { maxWidth: maxWidth, maxHeight: maxHeight }); }, hitTest: function(x, y, eventToFire) { this.hitTestInternal(x, y, eventToFire); }, hitTestWithReply: function(x, y, opt_callback) { this.hitTestInternal(x, y, 'hitTestResult', opt_callback); }, hitTestInternal: function(x, y, eventToFire, opt_callback) { // Convert from global to tree-relative coordinates. var location = GetLocation(this.treeID, GetRootID(this.treeID)); this.performAction_('hitTest', { x: Math.floor(x - location.left), y: Math.floor(y - location.top), eventToFire: eventToFire }, opt_callback); }, makeVisible: function() { this.performAction_('makeVisible'); }, performCustomAction: function(customActionId) { this.performAction_('customAction', { customActionID: customActionId }); }, resumeMedia: function() { this.performAction_('resumeMedia'); }, scrollBackward: function(opt_callback) { this.performAction_('scrollBackward', {}, opt_callback); }, scrollForward: function(opt_callback) { this.performAction_('scrollForward', {}, opt_callback); }, scrollUp: function(opt_callback) { this.performAction_('scrollUp', {}, opt_callback); }, scrollDown: function(opt_callback) { this.performAction_('scrollDown', {}, opt_callback); }, scrollLeft: function(opt_callback) { this.performAction_('scrollLeft', {}, opt_callback); }, scrollRight: function(opt_callback) { this.performAction_('scrollRight', {}, opt_callback); }, setSelection: function(startIndex, endIndex) { if (this.state.editable) { this.performAction_('setSelection', { focusNodeID: this.id, anchorOffset: startIndex, focusOffset: endIndex }); } }, setSequentialFocusNavigationStartingPoint: function() { this.performAction_('setSequentialFocusNavigationStartingPoint'); }, showContextMenu: function() { this.performAction_('showContextMenu'); }, startDuckingMedia: function() { this.performAction_('startDuckingMedia'); }, stopDuckingMedia: function() { this.performAction_('stopDuckingMedia'); }, suspendMedia: function() { this.performAction_('suspendMedia'); }, domQuerySelector: function(selector, callback) { if (!this.rootImpl) callback(); automationInternal.querySelector( { treeID: this.rootImpl.treeID, automationNodeID: this.id, selector: selector }, $Function.bind(this.domQuerySelectorCallback_, this, callback)); }, find: function(params) { return this.findInternal_(params); }, findAll: function(params) { return this.findInternal_(params, []); }, matches: function(params) { return this.matchInternal_(params); }, addEventListener: function(eventType, callback, capture) { this.removeEventListener(eventType, callback); if (!this.listeners[eventType]) this.listeners[eventType] = []; $Array.push(this.listeners[eventType], { __proto__: null, callback: callback, capture: !!capture, }); }, // TODO(dtseng/aboxhall): Check this impl against spec. removeEventListener: function(eventType, callback) { if (this.listeners[eventType]) { var listeners = this.listeners[eventType]; for (var i = 0; i < listeners.length; i++) { if (callback === listeners[i].callback) $Array.splice(listeners, i, 1); } } }, toJSON: function() { return { treeID: this.treeID, id: this.id, role: this.role, attributes: this.attributes }; }, dispatchEvent: function(eventType, eventFrom, mouseX, mouseY) { var path = []; var parent = this.parent; while (parent) { $Array.push(path, parent); parent = parent.parent; } var event = new AutomationEvent(eventType, this.wrapper, eventFrom); event.mouseX = mouseX; event.mouseY = mouseY; // Dispatch the event through the propagation path in three phases: // - capturing: starting from the root and going down to the target's parent // - targeting: dispatching the event on the target itself // - bubbling: starting from the target's parent, going back up to the root. // At any stage, a listener may call stopPropagation() on the event, which // will immediately stop event propagation through this path. if (this.dispatchEventAtCapturing_(event, path)) { if (this.dispatchEventAtTargeting_(event, path)) this.dispatchEventAtBubbling_(event, path); } }, toString: function() { var parentID = GetParentID(this.treeID, this.id); var childTreeID = GetIntAttribute(this.treeID, this.id, 'childTreeId'); var count = GetChildCount(this.treeID, this.id); var childIDs = []; for (var i = 0; i < count; ++i) { var childID = GetChildIDAtIndex(this.treeID, this.id, i); $Array.push(childIDs, childID); } var result = 'node id=' + this.id + ' role=' + this.role + ' state=' + $JSON.stringify(this.state) + ' parentID=' + parentID + ' childIds=' + $JSON.stringify(childIDs); if (this.hostNode_) { var hostNodeImpl = privates(this.hostNode_).impl; result += ' host treeID=' + hostNodeImpl.treeID + ' host nodeID=' + hostNodeImpl.id; } if (childTreeID) result += ' childTreeID=' + childTreeID; return result; }, dispatchEventAtCapturing_: function(event, path) { privates(event).impl.eventPhase = Event.CAPTURING_PHASE; for (var i = path.length - 1; i >= 0; i--) { this.fireEventListeners_(path[i], event); if (privates(event).impl.propagationStopped) return false; } return true; }, dispatchEventAtTargeting_: function(event) { privates(event).impl.eventPhase = Event.AT_TARGET; this.fireEventListeners_(this.wrapper, event); return !privates(event).impl.propagationStopped; }, dispatchEventAtBubbling_: function(event, path) { privates(event).impl.eventPhase = Event.BUBBLING_PHASE; for (var i = 0; i < path.length; i++) { this.fireEventListeners_(path[i], event); if (privates(event).impl.propagationStopped) return false; } return true; }, fireEventListeners_: function(node, event) { var nodeImpl = privates(node).impl; if (!nodeImpl.rootImpl) return; var listeners = nodeImpl.listeners[event.type]; if (!listeners) return; var eventPhase = event.eventPhase; for (var i = 0; i < listeners.length; i++) { if (eventPhase == Event.CAPTURING_PHASE && !listeners[i].capture) continue; if (eventPhase == Event.BUBBLING_PHASE && listeners[i].capture) continue; try { listeners[i].callback(event); } catch (e) { exceptionHandler.handle('Error in event handler for ' + event.type + ' during phase ' + eventPhase, e); } } }, performAction_: function(actionType, opt_args, opt_callback) { if (!this.rootImpl) return; // Not yet initialized. if (this.rootImpl.treeID === undefined || this.id === undefined) { return; } // Check permissions. if (!IsInteractPermitted()) { throw new Error(actionType + ' requires {"desktop": true} or' + ' {"interact": true} in the "automation" manifest key.'); } var requestID = -1; if (opt_callback) { requestID = this.rootImpl.addActionResultCallback(opt_callback); } automationInternal.performAction({ treeID: this.rootImpl.treeID, automationNodeID: this.id, actionType: actionType, requestID: requestID}, opt_args || {}); }, domQuerySelectorCallback_: function(userCallback, resultAutomationNodeID) { // resultAutomationNodeID could be zero or undefined or (unlikely) null; // they all amount to the same thing here, which is that no node was // returned. if (!resultAutomationNodeID || !this.rootImpl) { userCallback(null); return; } var resultNode = this.rootImpl.get(resultAutomationNodeID); if (!resultNode) { logging.WARNING('Query selector result not in tree: ' + resultAutomationNodeID); userCallback(null); } userCallback(resultNode); }, findInternal_: function(params, opt_results) { var result = null; this.forAllDescendants_(function(node) { if (privates(node).impl.matchInternal_(params)) { if (opt_results) $Array.push(opt_results, node); else result = node; return !opt_results; } }); if (opt_results) return opt_results; return result; }, /** * Executes a closure for all of this node's descendants, in pre-order. * Early-outs if the closure returns true. * @param {Function(AutomationNode):boolean} closure Closure to be executed * for each node. Return true to early-out the traversal. */ forAllDescendants_: function(closure) { var stack = $Array.reverse(this.wrapper.children); while (stack.length > 0) { var node = $Array.pop(stack); if (closure(node)) return; var children = node.children; for (var i = children.length - 1; i >= 0; i--) $Array.push(stack, children[i]); } }, matchInternal_: function(params) { if ($Object.keys(params).length === 0) return false; if ('role' in params && this.role != params.role) return false; if ('state' in params) { for (var state in params.state) { if (params.state[state] != (state in this.state)) return false; } } if ('attributes' in params) { for (var attribute in params.attributes) { var attrValue = params.attributes[attribute]; if (typeof attrValue != 'object') { if (this[attribute] !== attrValue) return false; } else if (attrValue instanceof $RegExp.self) { if (typeof this[attribute] != 'string') return false; if (!attrValue.test(this[attribute])) return false; } else { // TODO(aboxhall): handle intlist case. return false; } } } return true; } }; var stringAttributes = [ 'accessKey', 'ariaInvalidValue', 'autoComplete', 'className', 'containerLiveRelevant', 'containerLiveStatus', 'description', 'display', 'htmlTag', 'imageDataUrl', 'language', 'liveRelevant', 'liveStatus', 'name', 'placeholder', 'roleDescription', 'textInputType', 'url', 'value']; var boolAttributes = [ 'busy', 'clickable', 'containerLiveAtomic', 'containerLiveBusy', 'liveAtomic', 'scrollable' ]; var intAttributes = [ 'backgroundColor', 'color', 'colorValue', 'hierarchicalLevel', 'posInSet', 'scrollX', 'scrollXMax', 'scrollXMin', 'scrollY', 'scrollYMax', 'scrollYMin', 'setSize', 'tableCellColumnIndex', 'ariaCellColumnIndex', 'tableCellColumnSpan', 'tableCellRowIndex', 'ariaCellRowIndex', 'tableCellRowSpan', 'tableColumnCount', 'ariaColumnCount', 'tableColumnIndex', 'tableRowCount', 'ariaRowCount', 'tableRowIndex', 'textSelEnd', 'textSelStart']; var nodeRefAttributes = [ ['activedescendantId', 'activeDescendant'], ['inPageLinkTargetId', 'inPageLinkTarget'], ['nextFocusId', 'nextFocus'], ['nextOnLineId', 'nextOnLine'], ['previousFocusId', 'previousFocus'], ['previousOnLineId', 'previousOnLine'], ['tableColumnHeaderId', 'tableColumnHeader'], ['tableHeaderId', 'tableHeader'], ['tableRowHeaderId', 'tableRowHeader']]; var intListAttributes = [ 'lineBreaks', 'markerEnds', 'markerStarts', 'markerTypes', 'wordEnds', 'wordStarts']; var nodeRefListAttributes = [ ['controlsIds', 'controls'], ['describedbyIds', 'describedBy'], ['flowtoIds', 'flowTo'], ['labelledbyIds', 'labelledBy']]; var floatAttributes = [ 'valueForRange', 'minValueForRange', 'maxValueForRange']; var htmlAttributes = [ ['type', 'inputType']]; var publicAttributes = []; $Array.forEach(stringAttributes, function(attributeName) { $Array.push(publicAttributes, attributeName); $Object.defineProperty(AutomationNodeImpl.prototype, attributeName, { __proto__: null, get: function() { return GetStringAttribute(this.treeID, this.id, attributeName); } }); }); $Array.forEach(boolAttributes, function(attributeName) { $Array.push(publicAttributes, attributeName); $Object.defineProperty(AutomationNodeImpl.prototype, attributeName, { __proto__: null, get: function() { return GetBoolAttribute(this.treeID, this.id, attributeName); } }); }); $Array.forEach(intAttributes, function(attributeName) { $Array.push(publicAttributes, attributeName); $Object.defineProperty(AutomationNodeImpl.prototype, attributeName, { __proto__: null, get: function() { return GetIntAttribute(this.treeID, this.id, attributeName); } }); }); $Array.forEach(nodeRefAttributes, function(params) { var srcAttributeName = params[0]; var dstAttributeName = params[1]; $Array.push(publicAttributes, dstAttributeName); $Object.defineProperty(AutomationNodeImpl.prototype, dstAttributeName, { __proto__: null, get: function() { var id = GetIntAttribute(this.treeID, this.id, srcAttributeName); if (id && this.rootImpl) return this.rootImpl.get(id); else return undefined; } }); }); $Array.forEach(intListAttributes, function(attributeName) { $Array.push(publicAttributes, attributeName); $Object.defineProperty(AutomationNodeImpl.prototype, attributeName, { __proto__: null, get: function() { return GetIntListAttribute(this.treeID, this.id, attributeName); } }); }); $Array.forEach(nodeRefListAttributes, function(params) { var srcAttributeName = params[0]; var dstAttributeName = params[1]; $Array.push(publicAttributes, dstAttributeName); $Object.defineProperty(AutomationNodeImpl.prototype, dstAttributeName, { __proto__: null, get: function() { var ids = GetIntListAttribute(this.treeID, this.id, srcAttributeName); if (!ids || !this.rootImpl) return undefined; var result = []; for (var i = 0; i < ids.length; ++i) { var node = this.rootImpl.get(ids[i]); if (node) $Array.push(result, node); } return result; } }); }); $Array.forEach(floatAttributes, function(attributeName) { $Array.push(publicAttributes, attributeName); $Object.defineProperty(AutomationNodeImpl.prototype, attributeName, { __proto__: null, get: function() { return GetFloatAttribute(this.treeID, this.id, attributeName); } }); }); $Array.forEach(htmlAttributes, function(params) { var srcAttributeName = params[0]; var dstAttributeName = params[1]; $Array.push(publicAttributes, dstAttributeName); $Object.defineProperty(AutomationNodeImpl.prototype, dstAttributeName, { __proto__: null, get: function() { return GetHtmlAttribute(this.treeID, this.id, srcAttributeName); } }); }); /** * AutomationRootNode. * * An AutomationRootNode is the javascript end of an AXTree living in the * browser. AutomationRootNode handles unserializing incremental updates from * the source AXTree. Each update contains node data that form a complete tree * after applying the update. * * A brief note about ids used through this class. The source AXTree assigns * unique ids per node and we use these ids to build a hash to the actual * AutomationNode object. * Thus, tree traversals amount to a lookup in our hash. * * The tree itself is identified by the accessibility tree id of the * renderer widget host. * @constructor */ function AutomationRootNodeImpl(treeID) { $Function.call(AutomationNodeImpl, this, this); this.treeID = treeID; this.axNodeDataCache_ = {__proto__: null}; this.actionRequestIDToCallback_ = {__proto__: null}; } utils.defineProperty(AutomationRootNodeImpl, 'idToAutomationRootNode_', {__proto__: null}); utils.defineProperty(AutomationRootNodeImpl, 'get', function(treeID) { var result = AutomationRootNodeImpl.idToAutomationRootNode_[treeID]; return result || undefined; }); utils.defineProperty(AutomationRootNodeImpl, 'getOrCreate', function(treeID) { if (AutomationRootNodeImpl.idToAutomationRootNode_[treeID]) return AutomationRootNodeImpl.idToAutomationRootNode_[treeID]; var result = new AutomationRootNode(treeID); AutomationRootNodeImpl.idToAutomationRootNode_[treeID] = result; return result; }); utils.defineProperty(AutomationRootNodeImpl, 'destroy', function(treeID) { delete AutomationRootNodeImpl.idToAutomationRootNode_[treeID]; }); AutomationRootNodeImpl.prototype = { __proto__: AutomationNodeImpl.prototype, /** * @type {boolean} */ isRootNode: true, /** * @type {number} */ treeID: -1, /** * The parent of this node from a different tree. * @type {?AutomationNode} * @private */ hostNode_: null, /** * A map from id to AutomationNode. * @type {Object.} * @private */ axNodeDataCache_: null, actionRequestCounter_: 0, actionRequestIDToCallback_: null, get id() { var result = GetRootID(this.treeID); // Don't return undefined, because the id is often passed directly // as an argument to a native binding that expects only a valid number. if (result === undefined) return -1; return result; }, get chromeChannel() { return GetStringAttribute(this.treeID, this.id, 'chromeChannel'); }, get docUrl() { return GetDocURL(this.treeID); }, get docTitle() { return GetDocTitle(this.treeID); }, get docLoaded() { return GetDocLoaded(this.treeID); }, get docLoadingProgress() { return GetDocLoadingProgress(this.treeID); }, get anchorObject() { var id = GetAnchorObjectID(this.treeID); if (id && id != -1) return this.get(id); else return undefined; }, get anchorOffset() { var id = GetAnchorObjectID(this.treeID); if (id && id != -1) return GetAnchorOffset(this.treeID); }, get anchorAffinity() { var id = GetAnchorObjectID(this.treeID); if (id && id != -1) return GetAnchorAffinity(this.treeID); }, get focusObject() { var id = GetFocusObjectID(this.treeID); if (id && id != -1) return this.get(id); else return undefined; }, get focusOffset() { var id = GetFocusObjectID(this.treeID); if (id && id != -1) return GetFocusOffset(this.treeID); }, get focusAffinity() { var id = GetFocusObjectID(this.treeID); if (id && id != -1) return GetFocusAffinity(this.treeID); }, get: function(id) { if (id == undefined) return undefined; if (id == this.id) return this.wrapper; var obj = this.axNodeDataCache_[id]; if (obj) return obj; obj = new AutomationNode(this); privates(obj).impl.treeID = this.treeID; privates(obj).impl.id = id; this.axNodeDataCache_[id] = obj; return obj; }, remove: function(id) { if (this.axNodeDataCache_[id]) privates(this.axNodeDataCache_[id]).impl.detach(); delete this.axNodeDataCache_[id]; }, destroy: function() { this.dispatchEvent('destroyed', 'none'); for (var id in this.axNodeDataCache_) this.remove(id); this.detach(); }, setHostNode(hostNode) { this.hostNode_ = hostNode; }, onAccessibilityEvent: function(eventParams) { var targetNode = this.get(eventParams.targetID); if (targetNode) { var targetNodeImpl = privates(targetNode).impl; targetNodeImpl.dispatchEvent( eventParams.eventType, eventParams.eventFrom, eventParams.mouseX, eventParams.mouseY); if (eventParams.actionRequestID != -1) { this.onActionResult(eventParams.actionRequestID, targetNode); } } else { logging.WARNING('Got ' + eventParams.eventType + ' event on unknown node: ' + eventParams.targetID + '; this: ' + this.id); } return true; }, addActionResultCallback: function(callback) { this.actionRequestIDToCallback_[++this.actionRequestCounter_] = callback; return this.actionRequestCounter_; }, onActionResult: function(requestID, result) { if (requestID in this.actionRequestIDToCallback_) { this.actionRequestIDToCallback_[requestID](result); delete this.actionRequestIDToCallback_[requestID]; } }, toString: function() { function toStringInternal(nodeImpl, indent) { if (!nodeImpl) return ''; var output = ''; if (nodeImpl.isRootNode) output += indent + 'tree id=' + nodeImpl.treeID + '\n'; output += indent + $Function.call(AutomationNodeImpl.prototype.toString, nodeImpl) + '\n'; indent += ' '; var children = nodeImpl.children; for (var i = 0; i < children.length; ++i) output += toStringInternal(privates(children[i]).impl, indent); return output; } return toStringInternal(this, ''); }, }; function AutomationNode() { privates(AutomationNode).constructPrivate(this, arguments); } utils.expose(AutomationNode, AutomationNodeImpl, { functions: [ 'doDefault', 'find', 'findAll', 'focus', 'getImageData', 'hitTest', 'hitTestWithReply', 'makeVisible', 'matches', 'performCustomAction', 'resumeMedia', 'scrollBackward', 'scrollForward', 'scrollUp', 'scrollDown', 'scrollLeft', 'scrollRight', 'setSelection', 'setSequentialFocusNavigationStartingPoint', 'showContextMenu', 'startDuckingMedia', 'stopDuckingMedia', 'suspendMedia', 'addEventListener', 'removeEventListener', 'domQuerySelector', 'toString', 'boundsForRange', ], readonly: $Array.concat(publicAttributes, [ 'parent', 'firstChild', 'lastChild', 'children', 'previousSibling', 'nextSibling', 'isRootNode', 'role', 'checked', 'restriction', 'state', 'location', 'indexInParent', 'lineStartOffsets', 'root', 'htmlAttributes', 'nameFrom', 'bold', 'italic', 'underline', 'lineThrough', 'customActions', 'unclippedLocation', ]), }); function AutomationRootNode() { privates(AutomationRootNode).constructPrivate(this, arguments); } utils.expose(AutomationRootNode, AutomationRootNodeImpl, { superclass: AutomationNode, readonly: [ 'chromeChannel', 'docTitle', 'docUrl', 'docLoaded', 'docLoadingProgress', 'anchorObject', 'anchorOffset', 'anchorAffinity', 'focusObject', 'focusOffset', 'focusAffinity', ], }); utils.defineProperty(AutomationRootNode, 'get', function(treeID) { return AutomationRootNodeImpl.get(treeID); }); utils.defineProperty(AutomationRootNode, 'getOrCreate', function(treeID) { return AutomationRootNodeImpl.getOrCreate(treeID); }); utils.defineProperty(AutomationRootNode, 'destroy', function(treeID) { AutomationRootNodeImpl.destroy(treeID); }); exports.$set('AutomationNode', AutomationNode); exports.$set('AutomationRootNode', AutomationRootNode); // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Custom binding for the browserAction API. var binding = apiBridge || require('binding').Binding.create('browserAction'); var setIcon = require('setIcon').setIcon; var getExtensionViews = requireNative('runtime').GetExtensionViews; var sendRequest = bindingUtil ? $Function.bind(bindingUtil.sendRequest, bindingUtil) : require('sendRequest').sendRequest; var jsLastError = bindingUtil ? undefined : require('lastError'); function hasLastError() { return bindingUtil ? bindingUtil.hasLastError() : jsLastError.hasError(chrome); } binding.registerCustomHook(function(bindingsAPI) { var apiFunctions = bindingsAPI.apiFunctions; apiFunctions.setHandleRequest('setIcon', function(details, callback) { setIcon(details, function(args) { sendRequest('browserAction.setIcon', [args, callback], apiBridge ? undefined : this.definition.parameters, undefined); }.bind(this)); }); apiFunctions.setCustomCallback('openPopup', function(name, request, callback, response) { if (!callback) return; if (hasLastError()) { callback(); } else { var views = getExtensionViews(-1, -1, 'POPUP'); callback(views.length > 0 ? views[0] : null); } }); }); if (!apiBridge) exports.$set('binding', binding.generate()); // Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Custom binding for the Cast Streaming RtpStream API. var binding = apiBridge || require('binding').Binding.create('cast.streaming.rtpStream'); var natives = requireNative('cast_streaming_natives'); binding.registerCustomHook(function(bindingsAPI, extensionId) { var apiFunctions = bindingsAPI.apiFunctions; apiFunctions.setHandleRequest('destroy', function(transportId) { natives.DestroyCastRtpStream(transportId); }); apiFunctions.setHandleRequest('getSupportedParams', function(transportId) { return natives.GetSupportedParamsCastRtpStream(transportId); }); apiFunctions.setHandleRequest('start', function(transportId, params) { natives.StartCastRtpStream(transportId, params); }); apiFunctions.setHandleRequest('stop', function(transportId) { natives.StopCastRtpStream(transportId); }); apiFunctions.setHandleRequest('toggleLogging', function(transportId, enable) { natives.ToggleLogging(transportId, enable); }); apiFunctions.setHandleRequest('getRawEvents', function(transportId, extraData, callback) { natives.GetRawEvents(transportId, extraData, callback); }); apiFunctions.setHandleRequest('getStats', function(transportId, callback) { natives.GetStats(transportId, callback); }); }); if (!apiBridge) exports.$set('binding', binding.generate()); // Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Custom binding for the Cast Streaming Session API. var binding = apiBridge || require('binding').Binding.create('cast.streaming.session'); var natives = requireNative('cast_streaming_natives'); binding.registerCustomHook(function(bindingsAPI, extensionId) { var apiFunctions = bindingsAPI.apiFunctions; apiFunctions.setHandleRequest('create', function(audioTrack, videoTrack, callback) { natives.CreateSession(audioTrack, videoTrack, callback); }); }); if (!apiBridge) exports.$set('binding', binding.generate()); // Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Custom binding for the Cast Streaming UdpTransport API. var binding = apiBridge || require('binding').Binding.create('cast.streaming.udpTransport'); var natives = requireNative('cast_streaming_natives'); binding.registerCustomHook(function(bindingsAPI, extensionId) { var apiFunctions = bindingsAPI.apiFunctions; apiFunctions.setHandleRequest('destroy', function(transportId) { natives.DestroyCastUdpTransport(transportId); }); apiFunctions.setHandleRequest('setDestination', function(transportId, destination) { natives.SetDestinationCastUdpTransport(transportId, destination); }); apiFunctions.setHandleRequest('setOptions', function(transportId, options) { natives.SetOptionsCastUdpTransport(transportId, options); }); }); if (!apiBridge) exports.$set('binding', binding.generate()); // Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Custom binding for the Cast Streaming Session API. var binding = apiBridge || require('binding').Binding.create('cast.streaming.receiverSession'); var natives = requireNative('cast_streaming_natives'); binding.registerCustomHook(function(bindingsAPI, extensionId) { var apiFunctions = bindingsAPI.apiFunctions; apiFunctions.setHandleRequest( 'createAndBind', function(ap, vp, local, weidgth, height, fr, url, cb, op) { natives.StartCastRtpReceiver( ap, vp, local, weidgth, height, fr, url, cb, op); }); }); if (!apiBridge) exports.$set('binding', binding.generate()); // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. var Event = require('event_bindings').Event; var sendRequest = require('sendRequest').sendRequest; var validate = require('schemaUtils').validate; function extendSchema(schema) { var extendedSchema = $Array.slice(schema); $Array.unshift(extendedSchema, {'type': 'string'}); return extendedSchema; } // TODO(devlin): Maybe find a way to combine this and ContentSetting. function ChromeSetting(prefKey, valueSchema, schema) { var getFunctionParameters = function(name) { var f = $Array.filter( schema.functions, function(f) { return f.name === name; })[0]; return f.parameters; }; this.get = function(details, callback) { var getSchema = getFunctionParameters('get'); validate([details, callback], getSchema); return sendRequest('types.ChromeSetting.get', [prefKey, details, callback], extendSchema(getSchema)); }; this.set = function(details, callback) { // The set schema included in the Schema object is generic, since it varies // per-setting. However, this is only ever for a single setting, so we can // enforce the types more thoroughly. var rawSetSchema = getFunctionParameters('set'); var rawSettingParam = rawSetSchema[0]; var props = $Object.assign({}, rawSettingParam.properties); props.value = valueSchema; var modSettingParam = { name: rawSettingParam.name, type: rawSettingParam.type, properties: props, }; var modSetSchema = $Array.slice(rawSetSchema); modSetSchema[0] = modSettingParam; validate([details, callback], modSetSchema); return sendRequest('types.ChromeSetting.set', [prefKey, details, callback], extendSchema(modSetSchema)); }; this.clear = function(details, callback) { var clearSchema = getFunctionParameters('clear'); validate([details, callback], clearSchema); return sendRequest('types.ChromeSetting.clear', [prefKey, details, callback], extendSchema(clearSchema)); }; this.onChange = new Event('types.ChromeSetting.' + prefKey + '.onChange'); }; exports.$set('ChromeSetting', ChromeSetting); // Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. var binding = apiBridge || require('binding').Binding.create('chromeWebViewInternal'); var contextMenusHandlers = require('contextMenusHandlers'); binding.registerCustomHook(function(bindingsAPI) { var apiFunctions = bindingsAPI.apiFunctions; var handlers = contextMenusHandlers.create(true /* isWebview */); apiFunctions.setHandleRequest( 'contextMenusCreate', handlers.requestHandlers.create); apiFunctions.setHandleRequest( 'contextMenusUpdate', handlers.requestHandlers.update); apiFunctions.setHandleRequest( 'contextMenusRemove', handlers.requestHandlers.remove); apiFunctions.setHandleRequest( 'contextMenusRemoveAll', handlers.requestHandlers.removeAll); }); if (!apiBridge) exports.$set('ChromeWebView', binding.generate()); // Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // This module implements chrome-specific API. // See web_view_api_methods.js for details. var ChromeWebView = getInternalApi ? getInternalApi('chromeWebViewInternal') : require('chromeWebViewInternal').ChromeWebView; var ChromeWebViewSchema = requireNative('schema_registry').GetSchema('chromeWebViewInternal'); var CreateEvent = require('guestViewEvents').CreateEvent; var GuestViewInternalNatives = requireNative('guest_view_internal'); var idGeneratorNatives = requireNative('id_generator'); var utils = require('utils'); var WebViewImpl = require('webView').WebViewImpl; // This is the only "webViewInternal.onClicked" named event for this renderer. // // Since we need an event per , we define events with suffix // (subEventName) in each of the . Behind the scenes, this event is // registered as a ContextMenusEvent, with filter set to the webview's // |viewInstanceId|. Any time a ContextMenusEvent is dispatched, we re-dispatch // it to the subEvent's listeners. This way // .contextMenus.onClicked behave as a regular chrome Event type. var ContextMenusEvent = CreateEvent('chromeWebViewInternal.onClicked'); // See comment above. var ContextMenusHandlerEvent = CreateEvent('chromeWebViewInternal.onContextMenuShow'); var jsEvent; function createCustomEvent(name, schema, options, webviewId) { if (bindingUtil) return bindingUtil.createCustomEvent(name, undefined, false, false); if (!jsEvent) jsEvent = require('event_bindings').Event; return new jsEvent(name, schema, options, webviewId); } // This event is exposed as .contextMenus.onClicked. function createContextMenusOnClickedEvent(webViewInstanceId, opt_eventName, opt_argSchemas, opt_eventOptions) { var subEventName = GetUniqueSubEventName(opt_eventName); var newEvent = createCustomEvent(subEventName, opt_argSchemas, opt_eventOptions, webViewInstanceId); var view = GuestViewInternalNatives.GetViewFromID(webViewInstanceId); if (view) { view.events.addScopedListener( ContextMenusEvent, $Function.bind(function() { // Re-dispatch to subEvent's listeners. $Function.apply(newEvent.dispatch, newEvent, $Array.slice(arguments)); }, newEvent), {instanceId: webViewInstanceId}); } return newEvent; } // This event is exposed as .contextMenus.onShow. function createContextMenusOnContextMenuEvent(webViewInstanceId, opt_eventName, opt_argSchemas, opt_eventOptions) { var subEventName = GetUniqueSubEventName(opt_eventName); var newEvent = createCustomEvent(subEventName, opt_argSchemas, opt_eventOptions, webViewInstanceId); var view = GuestViewInternalNatives.GetViewFromID(webViewInstanceId); if (view) { view.events.addScopedListener( ContextMenusHandlerEvent, $Function.bind(function(e) { var defaultPrevented = false; var event = { preventDefault: function() { defaultPrevented = true; } }; // Re-dispatch to subEvent's listeners. $Function.apply(newEvent.dispatch, newEvent, [event]); if (!defaultPrevented) { // TODO(lazyboy): Remove |items| parameter completely from // ChromeWebView.showContextMenu as we don't do anything useful with // it currently. var items = []; var guestInstanceId = GuestViewInternalNatives. GetViewFromID(webViewInstanceId).guest.getId(); ChromeWebView.showContextMenu(guestInstanceId, e.requestId, items); } }, newEvent), {instanceId: webViewInstanceId}); } return newEvent; } // ----------------------------------------------------------------------------- // WebViewContextMenusImpl object. // An instance of this class is exposed as .contextMenus. function WebViewContextMenusImpl(viewInstanceId) { this.viewInstanceId_ = viewInstanceId; } $Object.setPrototypeOf(WebViewContextMenusImpl.prototype, null); WebViewContextMenusImpl.prototype.create = function() { var args = $Array.concat([this.viewInstanceId_], $Array.slice(arguments)); return $Function.apply(ChromeWebView.contextMenusCreate, null, args); }; WebViewContextMenusImpl.prototype.remove = function() { var args = $Array.concat([this.viewInstanceId_], $Array.slice(arguments)); return $Function.apply(ChromeWebView.contextMenusRemove, null, args); }; WebViewContextMenusImpl.prototype.removeAll = function() { var args = $Array.concat([this.viewInstanceId_], $Array.slice(arguments)); return $Function.apply(ChromeWebView.contextMenusRemoveAll, null, args); }; WebViewContextMenusImpl.prototype.update = function() { var args = $Array.concat([this.viewInstanceId_], $Array.slice(arguments)); return $Function.apply(ChromeWebView.contextMenusUpdate, null, args); }; function WebViewContextMenus() { privates(WebViewContextMenus).constructPrivate(this, arguments); } utils.expose(WebViewContextMenus, WebViewContextMenusImpl, { functions: [ 'create', 'remove', 'removeAll', 'update', ], }); // ----------------------------------------------------------------------------- WebViewImpl.prototype.maybeSetupContextMenus = function() { if (!this.contextMenusOnContextMenuEvent_) { var eventName = 'chromeWebViewInternal.onContextMenuShow'; var eventSchema = utils.lookup(ChromeWebViewSchema.events, 'name', 'onShow'); var eventOptions = {supportsListeners: true, supportsLazyListeners: false}; this.contextMenusOnContextMenuEvent_ = createContextMenusOnContextMenuEvent( this.viewInstanceId, eventName, eventSchema, eventOptions); } var createContextMenus = $Function.bind(function() { return this.weakWrapper(function() { if (this.contextMenus_) { return this.contextMenus_; } this.contextMenus_ = new WebViewContextMenus(this.viewInstanceId); // Define 'onClicked' event property on |this.contextMenus_|. var getOnClickedEvent = $Function.bind(function() { return this.weakWrapper(function() { if (!this.contextMenusOnClickedEvent_) { var eventName = 'chromeWebViewInternal.onClicked'; var eventSchema = utils.lookup(ChromeWebViewSchema.events, 'name', 'onClicked'); var eventOptions = {supportsListeners: true, supportsLazyListeners: false}; var onClickedEvent = createContextMenusOnClickedEvent( this.viewInstanceId, eventName, eventSchema, eventOptions); this.contextMenusOnClickedEvent_ = onClickedEvent; return onClickedEvent; } return this.contextMenusOnClickedEvent_; }); }, this); $Object.defineProperty( this.contextMenus_, 'onClicked', {get: getOnClickedEvent(), enumerable: true}); $Object.defineProperty( this.contextMenus_, 'onShow', { get: this.weakWrapper(function() { return this.contextMenusOnContextMenuEvent_; }), enumerable: true }); return this.contextMenus_; }); }, this); // Expose .contextMenus object. $Object.defineProperty( this.element, 'contextMenus', { get: createContextMenus(), enumerable: true }); }; function GetUniqueSubEventName(eventName) { return eventName + '/' + idGeneratorNatives.GetNextId(); } // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Custom binding for the contentSettings API. var sendRequest = require('sendRequest').sendRequest; var validate = require('schemaUtils').validate; // Some content types have been removed and no longer correspond to a real // content setting. Instead, these always return a fixed dummy value, and issue // a warning when accessed. This maps the content type name to the dummy value. var DEPRECATED_CONTENT_TYPES = { __proto__: null, fullscreen: 'allow', mouselock: 'allow', }; function extendSchema(schema) { var extendedSchema = $Array.slice(schema); $Array.unshift(extendedSchema, {'type': 'string'}); return extendedSchema; } function ContentSetting(contentType, settingSchema, schema) { var getFunctionParameters = function(name) { var f = $Array.filter( schema.functions, function(f) { return f.name === name; })[0]; return f.parameters; }; this.get = function(details, callback) { var getSchema = getFunctionParameters('get'); validate([details, callback], getSchema); var dummySetting = DEPRECATED_CONTENT_TYPES[contentType]; if (dummySetting !== undefined) { console.warn('contentSettings.' + contentType + ' is deprecated; it will ' + 'always return \'' + dummySetting + '\'.'); $Function.apply(callback, undefined, [{setting: dummySetting}]); return; } return sendRequest('contentSettings.get', [contentType, details, callback], extendSchema(getSchema)); }; this.set = function(details, callback) { // We check if the setting is deprecated first, since the validation will // fail for deprecated types. if ($Object.hasOwnProperty(DEPRECATED_CONTENT_TYPES, contentType)) { console.warn('contentSettings.' + contentType + ' is deprecated; setting ' + 'it has no effect.'); $Function.apply(callback, undefined, []); return; } // The set schema included in the Schema object is generic, since it varies // per-setting. However, this is only ever for a single setting, so we can // enforce the types more thoroughly. var rawSetSchema = getFunctionParameters('set'); var rawSettingParam = rawSetSchema[0]; var props = $Object.assign({}, rawSettingParam.properties); props.setting = settingSchema; var modSettingParam = { name: rawSettingParam.name, type: rawSettingParam.type, properties: props, }; var modSetSchema = $Array.slice(rawSetSchema); modSetSchema[0] = modSettingParam; validate([details, callback], modSetSchema); return sendRequest('contentSettings.set', [contentType, details, callback], extendSchema(modSetSchema)); }; this.clear = function(details, callback) { var clearSchema = getFunctionParameters('clear'); validate([details, callback], clearSchema); if ($Object.hasOwnProperty(DEPRECATED_CONTENT_TYPES, contentType)) { console.warn('contentSettings.' + contentType + ' is deprecated; ' + 'clearing it has no effect.'); $Function.apply(callback, undefined, []); return; } return sendRequest('contentSettings.clear', [contentType, details, callback], extendSchema(clearSchema)); }; this.getResourceIdentifiers = function(callback) { var schema = getFunctionParameters('getResourceIdentifiers'); validate([callback], schema); if ($Object.hasOwnProperty(DEPRECATED_CONTENT_TYPES, contentType)) { $Function.apply(callback, undefined, []); return; } return sendRequest( 'contentSettings.getResourceIdentifiers', [contentType, callback], extendSchema(schema)); }; } exports.$set('ContentSetting', ContentSetting); // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Custom binding for the declarativeContent API. var binding = apiBridge || require('binding').Binding.create('declarativeContent'); if (!apiBridge) { var utils = require('utils'); var validate = require('schemaUtils').validate; var canonicalizeCompoundSelector = requireNative('css_natives').CanonicalizeCompoundSelector; } var setIcon = require('setIcon').setIcon; binding.registerCustomHook(function(api) { var declarativeContent = api.compiledApi; if (apiBridge) { // Validation for most types is done in the native C++ with native bindings, // but setIcon is funny (and sadly broken). Ideally, we can move this // validation entirely into the native code, and this whole file can go // away. var nativeSetIcon = declarativeContent.SetIcon; declarativeContent.SetIcon = function(parameters) { // TODO(devlin): This is very, very wrong. setIcon() is potentially // asynchronous (in the case of a path being specified), which means this // becomes an "asynchronous constructor". Errors can be thrown *after* the // `new declarativeContent.SetIcon(...)` call, and in the async cases, // this wouldn't work when we immediately add the action via an API call // (e.g., // chrome.declarativeContent.onPageChange.addRules( // [{conditions: ..., actions: [ new SetIcon(...) ]}]); // ). Some of this is tracked in http://crbug.com/415315. setIcon(parameters, $Function.bind(function(data) { // Fake calling the original function as a constructor. $Object.setPrototypeOf(this, nativeSetIcon.prototype); $Function.apply(nativeSetIcon, this, [data]); }, this)); }; return; } // Returns the schema definition of type |typeId| defined in |namespace|. function getSchema(typeId) { return utils.lookup(api.schema.types, 'id', 'declarativeContent.' + typeId); } // Helper function for the constructor of concrete datatypes of the // declarative content API. // Makes sure that |this| contains the union of parameters and // {'instanceType': 'declarativeContent.' + typeId} and validates the // generated union dictionary against the schema for |typeId|. function setupInstance(instance, parameters, typeId) { for (var key in parameters) { if ($Object.hasOwnProperty(parameters, key)) { instance[key] = parameters[key]; } } instance.instanceType = 'declarativeContent.' + typeId; var schema = getSchema(typeId); validate([instance], [schema]); } function canonicalizeCssSelectors(selectors) { for (var i = 0; i < selectors.length; i++) { var canonicalizedSelector = canonicalizeCompoundSelector(selectors[i]); if (canonicalizedSelector == '') { throw new Error( 'Element of \'css\' array must be a ' + 'list of valid compound selectors: ' + selectors[i]); } selectors[i] = canonicalizedSelector; } } // Setup all data types for the declarative content API. declarativeContent.PageStateMatcher = function(parameters) { setupInstance(this, parameters, 'PageStateMatcher'); if ($Object.hasOwnProperty(this, 'css')) { canonicalizeCssSelectors(this.css); } }; declarativeContent.ShowPageAction = function(parameters) { setupInstance(this, parameters, 'ShowPageAction'); }; declarativeContent.RequestContentScript = function(parameters) { setupInstance(this, parameters, 'RequestContentScript'); }; // TODO(rockot): Do not expose this in M39 stable. Making this restriction // possible will take some extra work. See http://crbug.com/415315 // Note: See also the SetIcon wrapper above for more issues. declarativeContent.SetIcon = function(parameters) { setIcon(parameters, $Function.bind(function(data) { setupInstance(this, data, 'SetIcon'); }, this)); }; }); if (!apiBridge) exports.$set('binding', binding.generate()); // Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Custom binding for the desktopCapture API. var binding = apiBridge || require('binding').Binding.create('desktopCapture'); var sendRequest = bindingUtil ? $Function.bind(bindingUtil.sendRequest, bindingUtil) : require('sendRequest').sendRequest; var idGenerator = requireNative('id_generator'); binding.registerCustomHook(function(bindingsAPI) { var apiFunctions = bindingsAPI.apiFunctions; var pendingRequests = {}; function onRequestResult(id, result, options) { if (id in pendingRequests) { var callback = pendingRequests[id]; delete pendingRequests[id]; callback(result, options); } } apiFunctions.setHandleRequest('chooseDesktopMedia', function(sources, target_tab, callback) { // |target_tab| is an optional parameter. if (callback === undefined) { callback = target_tab; target_tab = undefined; } var id = idGenerator.GetNextId(); pendingRequests[id] = callback; sendRequest('desktopCapture.chooseDesktopMedia', [id, sources, target_tab, $Function.bind(onRequestResult, null, id)], apiBridge ? undefined : this.definition.parameters, undefined); return id; }); apiFunctions.setHandleRequest('cancelChooseDesktopMedia', function(id) { if (id in pendingRequests) { delete pendingRequests[id]; sendRequest('desktopCapture.cancelChooseDesktopMedia', [id], apiBridge ? undefined : this.definition.parameters, undefined); } }); }); if (!apiBridge) exports.$set('binding', binding.generate()); // Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Custom binding for the developerPrivate API. var binding = apiBridge || require('binding').Binding.create('developerPrivate'); binding.registerCustomHook(function(bindingsAPI) { var apiFunctions = bindingsAPI.apiFunctions; // Converts the argument of |functionName| from DirectoryEntry to URL. function bindFileSystemFunction(functionName) { apiFunctions.setUpdateArgumentsPostValidate( functionName, function(directoryEntry, callback) { var fileSystemName = directoryEntry.filesystem.name; var relativePath = $String.slice(directoryEntry.fullPath, 1); var url = directoryEntry.toURL(); return [fileSystemName, relativePath, url, callback]; }); } bindFileSystemFunction('loadDirectory'); // developerPrivate.enable is the same as chrome.management.setEnabled. // TODO(devlin): Migrate callers off developerPrivate.enable. bindingsAPI.compiledApi.enable = chrome.management.setEnabled; apiFunctions.setHandleRequest('allowFileAccess', function(id, allow, callback) { chrome.developerPrivate.updateExtensionConfiguration( {extensionId: id, fileAccess: allow}, callback); }); apiFunctions.setHandleRequest('allowIncognito', function(id, allow, callback) { chrome.developerPrivate.updateExtensionConfiguration( {extensionId: id, incognitoAccess: allow}, callback); }); apiFunctions.setHandleRequest('inspect', function(options, callback) { var renderViewId = options.render_view_id; if (typeof renderViewId == 'string') { renderViewId = parseInt(renderViewId); if (isNaN(renderViewId)) throw new Error('Invalid value for render_view_id'); } var renderProcessId = options.render_process_id; if (typeof renderProcessId == 'string') { renderProcessId = parseInt(renderProcessId); if (isNaN(renderProcessId)) throw new Error('Invalid value for render_process_id'); } chrome.developerPrivate.openDevTools({ extensionId: options.extension_id, renderProcessId: renderProcessId, renderViewId: renderViewId, incognito: options.incognito }, callback); }); }); if (!apiBridge) exports.$set('binding', binding.generate()); // Copyright (c) 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Custom bindings for the downloads API. var binding = apiBridge || require('binding').Binding.create('downloads'); var downloadsInternal = getInternalApi ? getInternalApi('downloadsInternal') : require('binding').Binding.create('downloadsInternal').generate(); var registerArgumentMassager = bindingUtil ? $Function.bind(bindingUtil.registerEventArgumentMassager, bindingUtil) : require('event_bindings').registerArgumentMassager; registerArgumentMassager('downloads.onDeterminingFilename', function(args, dispatch) { var downloadItem = args[0]; // Copy the id so that extensions can't change it. var downloadId = downloadItem.id; var suggestable = true; function isValidResult(result) { if (result === undefined) return false; if (typeof(result) != 'object') { console.error('Error: Invocation of form suggest(' + typeof(result) + ') doesn\'t match definition suggest({filename: string, ' + 'conflictAction: string})'); return false; } else if ((typeof(result.filename) != 'string') || (result.filename.length == 0)) { console.error('Error: "filename" parameter to suggest() must be a ' + 'non-empty string'); return false; } else if ([undefined, 'uniquify', 'overwrite', 'prompt'].indexOf( result.conflictAction) < 0) { console.error('Error: "conflictAction" parameter to suggest() must be ' + 'one of undefined, "uniquify", "overwrite", "prompt"'); return false; } return true; } function suggestCallback(result) { if (!suggestable) { console.error('suggestCallback may not be called more than once.'); return; } suggestable = false; if (isValidResult(result)) { downloadsInternal.determineFilename( downloadId, result.filename, result.conflictAction || ""); } else { downloadsInternal.determineFilename(downloadId, "", ""); } } try { var results = dispatch([downloadItem, suggestCallback]); var async = (results && results.results && (results.results.length != 0) && (results.results[0] === true)); if (suggestable && !async) suggestCallback(); } catch (e) { suggestCallback(); throw e; } }); if (!apiBridge) exports.$set('binding', binding.generate()); // Copyright 2017 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. var Event = require('event_bindings').Event; // The EasyUnlockProximityRequired object is just a stub that has an onChange // event, which is never triggered. // TODO(devlin): Remove this once the preferencesPrivate API is fully removed. // https://crbug.com/593166 function EasyUnlockProximityRequired(prefKey, valueSchema, schema) { // Note: technically, extensions could intercept this through a setter on // Object.prototype(). We don't really care, because a) this is only for a // private API, so we shouldn't have to worry about untrusted code, and b) // this is an anonymous event, which exposes no attack surface and will be // exposed to the extension anyway. this.onChange = new Event(); }; exports.$set('EasyUnlockProximityRequired', EasyUnlockProximityRequired); // Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Custom bindings for the feedbackPrivate API. var binding = apiBridge || require('binding').Binding.create('feedbackPrivate'); var blobNatives = requireNative('blob_natives'); binding.registerCustomHook(function(bindingsAPI) { var apiFunctions = bindingsAPI.apiFunctions; apiFunctions.setUpdateArgumentsPostValidate( "sendFeedback", function(feedbackInfo, callback) { var attachedFileBlobUuid = ''; var screenshotBlobUuid = ''; if (feedbackInfo.attachedFile) attachedFileBlobUuid = blobNatives.GetBlobUuid(feedbackInfo.attachedFile.data); if (feedbackInfo.screenshot) screenshotBlobUuid = blobNatives.GetBlobUuid(feedbackInfo.screenshot); feedbackInfo.attachedFileBlobUuid = attachedFileBlobUuid; feedbackInfo.screenshotBlobUuid = screenshotBlobUuid; return [feedbackInfo, callback]; }); }); if (!apiBridge) exports.$set('binding', binding.generate()); // Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Custom binding for the GCM API. var binding = apiBridge || require('binding').Binding.create('gcm'); var forEach = require('utils').forEach; binding.registerCustomHook(function(bindingsAPI) { var apiFunctions = bindingsAPI.apiFunctions; var gcm = bindingsAPI.compiledApi; apiFunctions.setUpdateArgumentsPostValidate( 'send', function(message, callback) { // Validate message.data. var payloadSize = 0; forEach(message.data, function(property, value) { if (property.length == 0) throw new Error("One of data keys is empty."); var lowerCasedProperty = property.toLowerCase(); // Issue an error for forbidden prefixes of property names. if (lowerCasedProperty.startsWith("goog.") || lowerCasedProperty.startsWith("google") || property.startsWith("collapse_key")) { throw new Error("Invalid data key: " + property); } payloadSize += property.length + value.length; }); if (payloadSize > gcm.MAX_MESSAGE_SIZE) throw new Error("Payload exceeded allowed size limit. Payload size is: " + payloadSize); if (payloadSize == 0) throw new Error("No data to send."); return arguments; }); }); if (!apiBridge) exports.$set('binding', binding.generate()); // Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Custom binding for the Identity API. var binding = apiBridge || require('binding').Binding.create('identity'); binding.registerCustomHook(function(binding, id, contextType) { var apiFunctions = binding.apiFunctions; apiFunctions.setHandleRequest('getRedirectURL', function(path) { if (path === null || path === undefined) path = '/'; else path = String(path); if (path[0] != '/') path = '/' + path; return 'https://' + id + '.chromiumapp.org' + path; }); }); if (!apiBridge) exports.$set('binding', binding.generate()); // Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Custom binding for the image writer private API. var binding = apiBridge || require('binding').Binding.create('imageWriterPrivate'); binding.registerCustomHook(function(bindingsAPI) { var apiFunctions = bindingsAPI.apiFunctions; apiFunctions.setUpdateArgumentsPostValidate( 'writeFromFile', function(device, fileEntry, options, callback) { var fileSystemName = fileEntry.filesystem.name; var relativePath = $String.slice(fileEntry.fullPath, 1); return [device, fileSystemName, relativePath, callback]; }); }); if (!apiBridge) exports.$set('binding', binding.generate()); // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Custom binding for the input ime API. Only injected into the // v8 contexts for extensions which have permission for the API. var binding = apiBridge || require('binding').Binding.create('input.ime'); var appWindowNatives = requireNative('app_window_natives'); var registerArgumentMassager = bindingUtil ? $Function.bind(bindingUtil.registerEventArgumentMassager, bindingUtil) : require('event_bindings').registerArgumentMassager; // TODO(crbug.com/733825): These bindings have some issues. var inputIme; registerArgumentMassager('input.ime.onKeyEvent', function(args, dispatch) { var keyData = args[1]; var result = false; try { // dispatch() is weird - it returns an object {results: array} iff // there is at least one result value that !== undefined. Since onKeyEvent // has a maximum of one listener, we know that any result we find is the one // we're interested in. var dispatchResult = dispatch(args); if (dispatchResult && dispatchResult.results) result = dispatchResult.results[0]; } catch (e) { console.error('Error in event handler for onKeyEvent: ' + e.stack); } if (!inputIme.onKeyEvent.async) inputIme.keyEventHandled(keyData.requestId, result); }); binding.registerCustomHook(function(api) { inputIme = api.compiledApi; var originalAddListener = inputIme.onKeyEvent.addListener; inputIme.onKeyEvent.addListener = function(cb, opt_extraInfo) { inputIme.onKeyEvent.async = false; if (opt_extraInfo instanceof Array) { for (var i = 0; i < opt_extraInfo.length; ++i) { if (opt_extraInfo[i] == 'async') { inputIme.onKeyEvent.async = true; } } } $Function.call(originalAddListener, this, cb); }; api.apiFunctions.setCustomCallback('createWindow', function(name, request, callback, windowParams) { if (!callback) { return; } var view; if (windowParams && windowParams.frameId) { view = appWindowNatives.GetFrame( windowParams.frameId, false /* notifyBrowser */); view.id = windowParams.frameId; } callback(view); }); }); if (!apiBridge) exports.$set('binding', binding.generate()); // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Custom binding for the Media Gallery API. var binding = apiBridge || require('binding').Binding.create('mediaGalleries'); var blobNatives = requireNative('blob_natives'); var mediaGalleriesNatives = requireNative('mediaGalleries'); var sendRequest = bindingUtil ? $Function.bind(bindingUtil.sendRequest, bindingUtil) : require('sendRequest').sendRequest; var blobsAwaitingMetadata = {}; var mediaGalleriesMetadata = {}; function createFileSystemObjectsAndUpdateMetadata(response) { var result = []; mediaGalleriesMetadata = {}; // Clear any previous metadata. if (response) { for (var i = 0; i < response.length; i++) { var filesystem = mediaGalleriesNatives.GetMediaFileSystemObject( response[i].fsid); $Array.push(result, filesystem); var metadata = response[i]; delete metadata.fsid; mediaGalleriesMetadata[filesystem.name] = metadata; } } return result; } binding.registerCustomHook(function(bindingsAPI, extensionId) { var apiFunctions = bindingsAPI.apiFunctions; // getMediaFileSystems and addUserSelectedFolder use a custom callback so that // they can instantiate and return an array of file system objects. apiFunctions.setCustomCallback('getMediaFileSystems', function(name, request, callback, response) { var result = createFileSystemObjectsAndUpdateMetadata(response); if (callback) callback(result); }); apiFunctions.setCustomCallback('addUserSelectedFolder', function(name, request, callback, response) { var fileSystems = []; var selectedFileSystemName = ""; if (response && 'mediaFileSystems' in response && 'selectedFileSystemIndex' in response) { fileSystems = createFileSystemObjectsAndUpdateMetadata( response['mediaFileSystems']); var selectedFileSystemIndex = response['selectedFileSystemIndex']; if (selectedFileSystemIndex >= 0) { selectedFileSystemName = fileSystems[selectedFileSystemIndex].name; } } if (callback) callback(fileSystems, selectedFileSystemName); }); apiFunctions.setHandleRequest('getMediaFileSystemMetadata', function(filesystem) { if (filesystem && filesystem.name && filesystem.name in mediaGalleriesMetadata) { return mediaGalleriesMetadata[filesystem.name]; } return { 'name': '', 'galleryId': '', 'isRemovable': false, 'isMediaDevice': false, 'isAvailable': false, }; }); function getMetadataCallback(uuid, name, request, callback, response) { if (response && response.attachedImagesBlobInfo) { for (var i = 0; i < response.attachedImagesBlobInfo.length; i++) { var blobInfo = response.attachedImagesBlobInfo[i]; var blob = blobNatives.TakeBrowserProcessBlob( blobInfo.blobUUID, blobInfo.type, blobInfo.size); response.metadata.attachedImages.push(blob); } } if (callback) callback(response ? response.metadata : null); delete blobsAwaitingMetadata[uuid]; } apiFunctions.setHandleRequest('getMetadata', function(mediaFile, options, callback) { var blobUuid = blobNatives.GetBlobUuid(mediaFile) // Store the blob in a global object to keep its refcount nonzero -- this // prevents the object from being garbage collected before any metadata // parsing gets to occur (see crbug.com/415792). blobsAwaitingMetadata[blobUuid] = mediaFile; var optArgs = { __proto__: null, customCallback: $Function.bind(getMetadataCallback, null, blobUuid), }; sendRequest('mediaGalleries.getMetadata', [blobUuid, options, callback], bindingUtil ? undefined : this.definition.parameters, optArgs); }); }); if (!apiBridge) exports.$set('binding', binding.generate()); // Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Custom bindings for the notifications API. // var binding = apiBridge || require('binding').Binding.create('notifications'); var sendRequest = bindingUtil ? $Function.bind(bindingUtil.sendRequest, bindingUtil) : require('sendRequest').sendRequest; var exceptionHandler = require('uncaught_exception_handler'); var imageUtil = require('imageUtil'); var notificationsPrivate = requireNative('notifications_private'); var jsLastError = bindingUtil ? undefined : require('lastError'); function runCallbackWithLastError(name, message, stack, callback, args) { if (bindingUtil) { bindingUtil.runCallbackWithLastError(message, function() { $Function.apply(callback, null, args); }); } else { jsLastError.run(name, message, stack, callback, args); } } function imageDataSetter(context, key) { var f = function(val) { this[key] = val; }; return $Function.bind(f, context); } // A URL Spec is an object with the following keys: // path: The resource to be downloaded. // width: (optional) The maximum width of the image to be downloaded in device // pixels. // height: (optional) The maximum height of the image to be downloaded in // device pixels. // callback: A function to be called when the URL is complete. It // should accept an ImageData object and set the appropriate // field in |notificationDetails|. function getUrlSpecs(imageSizes, notificationDetails) { var urlSpecs = []; // |iconUrl| might be optional for notification updates. if (notificationDetails.iconUrl) { $Array.push(urlSpecs, { path: notificationDetails.iconUrl, width: imageSizes.icon.width * imageSizes.scaleFactor, height: imageSizes.icon.height * imageSizes.scaleFactor, callback: imageDataSetter(notificationDetails, 'iconBitmap') }); } // |appIconMaskUrl| is optional. if (notificationDetails.appIconMaskUrl) { $Array.push(urlSpecs, { path: notificationDetails.appIconMaskUrl, width: imageSizes.appIconMask.width * imageSizes.scaleFactor, height: imageSizes.appIconMask.height * imageSizes.scaleFactor, callback: imageDataSetter(notificationDetails, 'appIconMaskBitmap') }); } // |imageUrl| is optional. if (notificationDetails.imageUrl) { $Array.push(urlSpecs, { path: notificationDetails.imageUrl, width: imageSizes.image.width * imageSizes.scaleFactor, height: imageSizes.image.height * imageSizes.scaleFactor, callback: imageDataSetter(notificationDetails, 'imageBitmap') }); } // Each button has an optional icon. var buttonList = notificationDetails.buttons; if (buttonList && typeof buttonList.length === 'number') { var numButtons = buttonList.length; for (var i = 0; i < numButtons; i++) { if (buttonList[i].iconUrl) { $Array.push(urlSpecs, { path: buttonList[i].iconUrl, width: imageSizes.buttonIcon.width * imageSizes.scaleFactor, height: imageSizes.buttonIcon.height * imageSizes.scaleFactor, callback: imageDataSetter(buttonList[i], 'iconBitmap') }); } } } return urlSpecs; } function replaceNotificationOptionURLs(notification_details, callback) { var imageSizes = notificationsPrivate.GetNotificationImageSizes(); var url_specs = getUrlSpecs(imageSizes, notification_details); if (!url_specs.length) { callback(true); return; } var errors = 0; imageUtil.loadAllImages(url_specs, { onerror: function(index) { errors++; }, oncomplete: function(imageData) { if (errors > 0) { callback(false); return; } for (var index = 0; index < url_specs.length; index++) { var url_spec = url_specs[index]; url_spec.callback(imageData[index]); } callback(true); } }); } function genHandle(name, failure_function) { return function(id, input_notification_details, callback) { // TODO(dewittj): Remove this hack. This is used as a way to deep // copy a complex JSON object. var notification_details = $JSON.parse( $JSON.stringify(input_notification_details)); var that = this; var stack = exceptionHandler.getExtensionStackTrace(); replaceNotificationOptionURLs(notification_details, function(success) { if (success) { sendRequest( name, [id, notification_details, callback], bindingUtil ? undefined : that.definition.parameters, bindingUtil ? undefined : {__proto__: null, stack: stack}); return; } runCallbackWithLastError( name, 'Unable to download all specified images.', stack, failure_function, [callback || function() {}, id]); }); }; } var handleCreate = genHandle('notifications.create', function(callback, id) { callback(id); }); var handleUpdate = genHandle('notifications.update', function(callback, id) { callback(false); }); var notificationsCustomHook = function(bindingsAPI, extensionId) { var apiFunctions = bindingsAPI.apiFunctions; apiFunctions.setHandleRequest('create', handleCreate); apiFunctions.setHandleRequest('update', handleUpdate); }; binding.registerCustomHook(notificationsCustomHook); if (!apiBridge) exports.$set('binding', binding.generate()); // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Custom binding for the omnibox API. Only injected into the v8 contexts // for extensions which have permission for the omnibox API. var binding = apiBridge || require('binding').Binding.create('omnibox'); var registerArgumentMassager = bindingUtil ? $Function.bind(bindingUtil.registerEventArgumentMassager, bindingUtil) : require('event_bindings').registerArgumentMassager; var sendRequest = bindingUtil ? $Function.bind(bindingUtil.sendRequest, bindingUtil) : require('sendRequest').sendRequest; // Remove invalid characters from |text| so that it is suitable to use // for |AutocompleteMatch::contents|. function sanitizeString(text, shouldTrim) { // NOTE: This logic mirrors |AutocompleteMatch::SanitizeString()|. // 0x2028 = line separator; 0x2029 = paragraph separator. var kRemoveChars = /(\r|\n|\t|\u2028|\u2029)/gm; if (shouldTrim) text = text.trimLeft(); return text.replace(kRemoveChars, ''); } // Parses the xml syntax supported by omnibox suggestion results. Returns an // object with two properties: 'description', which is just the text content, // and 'descriptionStyles', which is an array of style objects in a format // understood by the C++ backend. function parseOmniboxDescription(input) { var domParser = new DOMParser(); // The XML parser requires a single top-level element, but we want to // support things like 'hello, world!'. So we wrap the // provided text in generated root level element. var root = domParser.parseFromString( '' + input + '', 'text/xml'); // DOMParser has a terrible error reporting facility. Errors come out nested // inside the returned document. var error = root.querySelector('parsererror div'); if (error) { throw new Error(error.textContent); } // Otherwise, it's valid, so build up the result. var result = { description: '', descriptionStyles: [] }; // Recursively walk the tree. function walk(node) { for (var i = 0, child; child = node.childNodes[i]; i++) { // Append text nodes to our description. if (child.nodeType == Node.TEXT_NODE) { var shouldTrim = result.description.length == 0; result.description += sanitizeString(child.nodeValue, shouldTrim); continue; } // Process and descend into a subset of recognized tags. if (child.nodeType == Node.ELEMENT_NODE && (child.nodeName == 'dim' || child.nodeName == 'match' || child.nodeName == 'url')) { var style = { 'type': child.nodeName, 'offset': result.description.length }; $Array.push(result.descriptionStyles, style); walk(child); style.length = result.description.length - style.offset; continue; } // Descend into all other nodes, even if they are unrecognized, for // forward compat. walk(child); } }; walk(root); return result; } binding.registerCustomHook(function(bindingsAPI) { var apiFunctions = bindingsAPI.apiFunctions; apiFunctions.setUpdateArgumentsPreValidate('setDefaultSuggestion', function(suggestResult) { if (suggestResult.content != undefined) { // null, etc. throw new Error( 'setDefaultSuggestion cannot contain the "content" field'); } return [suggestResult]; }); apiFunctions.setHandleRequest('setDefaultSuggestion', function(details) { var parseResult = parseOmniboxDescription(details.description); sendRequest('omnibox.setDefaultSuggestion', [parseResult], bindingUtil ? undefined : this.definition.parameters, undefined); }); apiFunctions.setUpdateArgumentsPostValidate( 'sendSuggestions', function(requestId, userSuggestions) { var suggestions = []; for (var i = 0; i < userSuggestions.length; i++) { var parseResult = parseOmniboxDescription( userSuggestions[i].description); parseResult.content = userSuggestions[i].content; parseResult.deletable = userSuggestions[i].deletable; $Array.push(suggestions, parseResult); } return [requestId, suggestions]; }); }); registerArgumentMassager('omnibox.onInputChanged', function(args, dispatch) { var text = args[0]; var requestId = args[1]; var suggestCallback = function(suggestions) { chrome.omnibox.sendSuggestions(requestId, suggestions); }; dispatch([text, suggestCallback]); }); if (!apiBridge) exports.$set('binding', binding.generate()); // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Custom binding for the pageAction API. var binding = apiBridge || require('binding').Binding.create('pageAction'); var setIcon = require('setIcon').setIcon; var sendRequest = bindingUtil ? $Function.bind(bindingUtil.sendRequest, bindingUtil) : require('sendRequest').sendRequest; binding.registerCustomHook(function(bindingsAPI) { var apiFunctions = bindingsAPI.apiFunctions; apiFunctions.setHandleRequest('setIcon', function(details, callback) { setIcon(details, $Function.bind(function(args) { sendRequest('pageAction.setIcon', [args, callback], bindingUtil ? undefined : this.definition.parameters, undefined); }, this)); }); }); if (!apiBridge) exports.$set('binding', binding.generate()); // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Custom binding for the pageCapture API. var binding = apiBridge || require('binding').Binding.create('pageCapture'); var handleUncaughtException = require('uncaught_exception_handler').handle; var pageCaptureNatives = requireNative('page_capture'); var CreateBlob = pageCaptureNatives.CreateBlob; var SendResponseAck = pageCaptureNatives.SendResponseAck; binding.registerCustomHook(function(bindingsAPI) { var apiFunctions = bindingsAPI.apiFunctions; apiFunctions.setCustomCallback('saveAsMHTML', function(name, request, callback, response) { if (response) response = CreateBlob(response.mhtmlFilePath, response.mhtmlFileLength); try { callback(response); } catch (e) { handleUncaughtException( 'Error in chrome.pageCapture.saveAsMHTML callback', e, request.stack); } finally { // Notify the browser. Now that the blob is referenced from JavaScript, // the browser can drop its reference to it. SendResponseAck(request.id); } }); }); if (!apiBridge) exports.$set('binding', binding.generate()); // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Custom binding for the syncFileSystem API. var binding = apiBridge || require('binding').Binding.create('syncFileSystem'); var registerArgumentMassager = bindingUtil ? $Function.bind(bindingUtil.registerEventArgumentMassager, bindingUtil) : require('event_bindings').registerArgumentMassager; var fileSystemNatives = requireNative('file_system_natives'); var syncFileSystemNatives = requireNative('sync_file_system'); binding.registerCustomHook(function(bindingsAPI) { var apiFunctions = bindingsAPI.apiFunctions; // Functions which take in an [instanceOf=FileEntry]. function bindFileEntryFunction(functionName) { apiFunctions.setUpdateArgumentsPostValidate( functionName, function(entry, callback) { var fileSystemUrl = entry.toURL(); return [fileSystemUrl, callback]; }); } $Array.forEach(['getFileStatus'], bindFileEntryFunction); // Functions which take in a FileEntry array. function bindFileEntryArrayFunction(functionName) { apiFunctions.setUpdateArgumentsPostValidate( functionName, function(entries, callback) { var fileSystemUrlArray = []; for (var i=0; i < entries.length; i++) { $Array.push(fileSystemUrlArray, entries[i].toURL()); } return [fileSystemUrlArray, callback]; }); } $Array.forEach(['getFileStatuses'], bindFileEntryArrayFunction); // Functions which take in an [instanceOf=DOMFileSystem]. function bindFileSystemFunction(functionName) { apiFunctions.setUpdateArgumentsPostValidate( functionName, function(filesystem, callback) { var fileSystemUrl = filesystem.root.toURL(); return [fileSystemUrl, callback]; }); } $Array.forEach(['getUsageAndQuota'], bindFileSystemFunction); // Functions which return an [instanceOf=DOMFileSystem]. apiFunctions.setCustomCallback('requestFileSystem', function(name, request, callback, response) { var result = null; if (response) { result = syncFileSystemNatives.GetSyncFileSystemObject( response.name, response.root); } if (callback) callback(result); }); // Functions which return an array of FileStatusInfo object // which has [instanceOf=FileEntry]. apiFunctions.setCustomCallback('getFileStatuses', function(name, request, callback, response) { var results = []; if (response) { for (var i = 0; i < response.length; i++) { var result = {}; var entry = response[i].entry; result.fileEntry = fileSystemNatives.GetFileEntry( entry.fileSystemType, entry.fileSystemName, entry.rootUrl, entry.filePath, entry.isDirectory); result.status = response[i].status; result.error = response[i].error; $Array.push(results, result); } } if (callback) callback(results); }); }); registerArgumentMassager('syncFileSystem.onFileStatusChanged', function(args, dispatch) { // Make FileEntry object using all the base string fields. var fileEntry = fileSystemNatives.GetFileEntry( args[0].fileSystemType, args[0].fileSystemName, args[0].rootUrl, args[0].filePath, args[0].isDirectory); // Combine into a single dictionary. var fileInfo = new Object(); fileInfo.fileEntry = fileEntry; fileInfo.status = args[1]; if (fileInfo.status == "synced") { fileInfo.action = args[2]; fileInfo.direction = args[3]; } dispatch([fileInfo]); }); if (!apiBridge) exports.$set('binding', binding.generate()); // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Custom binding for the systemIndicator API. // TODO(dewittj) Refactor custom binding to reduce redundancy between the // extension action APIs. var binding = apiBridge || require('binding').Binding.create('systemIndicator'); var setIcon = require('setIcon').setIcon; var sendRequest = bindingUtil ? $Function.bind(bindingUtil.sendRequest, bindingUtil) : require('sendRequest').sendRequest; binding.registerCustomHook(function(bindingsAPI) { var apiFunctions = bindingsAPI.apiFunctions; apiFunctions.setHandleRequest('setIcon', function(details, callback) { setIcon(details, $Function.bind(function(args) { sendRequest('systemIndicator.setIcon', [args, callback], bindingUtil ? undefined : this.definition.parameters, undefined); }, this)); }); }); if (!apiBridge) exports.$set('binding', binding.generate()); // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Custom binding for the Tab Capture API. var binding = apiBridge || require('binding').Binding.create('tabCapture'); var jsLastError = bindingUtil ? undefined : require('lastError'); function runCallbackWithLastError(name, message, stack, callback, args) { if (bindingUtil) { bindingUtil.runCallbackWithLastError(message, function() { $Function.apply(callback, null, args); }); } else { jsLastError.run(name, message, stack, callback, args); } } binding.registerCustomHook(function(bindingsAPI, extensionId) { var apiFunctions = bindingsAPI.apiFunctions; function proxyToGetUserMedia(name, request, callback, response) { if (!callback) return; if (!response) { // When the response is missing, runtime.lastError has already been set. // See chrome/browser/extensions/api/tab_capture/tab_capture_api.cc. callback(null); return; } // Convenience function for processing webkitGetUserMedia() error objects to // provide runtime.lastError messages for the tab capture API. function getErrorMessage(error, fallbackMessage) { if (!error || (typeof error.message != 'string')) return fallbackMessage; return error.message.replace(/(navigator\.)?(webkit)?GetUserMedia/gi, name); } var options = {}; if (response.audioConstraints) options.audio = response.audioConstraints; if (response.videoConstraints) options.video = response.videoConstraints; try { navigator.webkitGetUserMedia( options, function onSuccess(media_stream) { callback(media_stream); }, function onError(error) { runCallbackWithLastError( name, getErrorMessage(error, "Failed to start MediaStream."), request.stack, function() { callback(null); }); }); } catch (error) { runCallbackWithLastError( name, getErrorMessage(error, "Invalid argument(s)."), request.stack, function() { callback(null); }); } } apiFunctions.setCustomCallback('capture', proxyToGetUserMedia); apiFunctions.setCustomCallback('captureOffscreenTab', proxyToGetUserMedia); }); if (!apiBridge) exports.$set('binding', binding.generate()); // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Custom binding for the tabs API. var binding = apiBridge || require('binding').Binding.create('tabs'); var messaging = require('messaging'); var OpenChannelToTab = requireNative('messaging_natives').OpenChannelToTab; var sendRequestIsDisabled = requireNative('process').IsSendRequestDisabled(); var forEach = require('utils').forEach; binding.registerCustomHook(function(bindingsAPI, extensionId) { var apiFunctions = bindingsAPI.apiFunctions; var tabs = bindingsAPI.compiledApi; apiFunctions.setHandleRequest('connect', function(tabId, connectInfo) { var name = ''; var frameId = -1; if (connectInfo) { name = connectInfo.name || name; frameId = connectInfo.frameId; if (typeof frameId == 'undefined' || frameId < 0) frameId = -1; } var portId = OpenChannelToTab(tabId, frameId, extensionId, name); return messaging.createPort(portId, name); }); apiFunctions.setHandleRequest('sendRequest', function(tabId, request, responseCallback) { if (sendRequestIsDisabled) throw new Error(sendRequestIsDisabled); var port = tabs.connect(tabId, {name: messaging.kRequestChannel}); messaging.sendMessageImpl(port, request, responseCallback); }); apiFunctions.setHandleRequest('sendMessage', function(tabId, message, options, responseCallback) { var connectInfo = { name: messaging.kMessageChannel }; if (options) { forEach(options, function(k, v) { connectInfo[k] = v; }); } var port = tabs.connect(tabId, connectInfo); messaging.sendMessageImpl(port, message, responseCallback); }); }); if (!apiBridge) exports.$set('binding', binding.generate()); // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Custom binding for the tts API. var binding = apiBridge || require('binding').Binding.create('tts'); var idGenerator = requireNative('id_generator'); var sendRequest = bindingUtil ? $Function.bind(bindingUtil.sendRequest, bindingUtil) : require('sendRequest').sendRequest; var lazyBG = requireNative('lazy_background_page'); binding.registerCustomHook(function(api) { var apiFunctions = api.apiFunctions; var tts = api.compiledApi; var handlers = {}; function ttsEventListener(event) { var eventHandler = handlers[event.srcId]; if (eventHandler) { eventHandler({ type: event.type, charIndex: event.charIndex, errorMessage: event.errorMessage }); if (event.isFinalEvent) { delete handlers[event.srcId]; // Balanced in 'speak' handler. lazyBG.DecrementKeepaliveCount(); } } } // This file will get run if an extension needs the ttsEngine permission, but // it doesn't necessarily have the tts permission. If it doesn't, trying to // add a listener to chrome.tts.onEvent will fail. // See http://crbug.com/122474. try { tts.onEvent.addListener(ttsEventListener); } catch (e) {} apiFunctions.setHandleRequest('speak', function() { var args = $Array.from(arguments); if (args.length > 1 && args[1] && args[1].onEvent) { var id = idGenerator.GetNextId(); args[1].srcId = id; handlers[id] = args[1].onEvent; // Keep the page alive until the event finishes. // Balanced in eventHandler. lazyBG.IncrementKeepaliveCount(); } sendRequest('tts.speak', args, bindingUtil ? undefined : this.definition.parameters, undefined); return id; }); }); if (!apiBridge) exports.$set('binding', binding.generate()); // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Custom binding for the ttsEngine API. var binding = apiBridge || require('binding').Binding.create('ttsEngine'); var registerArgumentMassager = bindingUtil ? $Function.bind(bindingUtil.registerEventArgumentMassager, bindingUtil) : require('event_bindings').registerArgumentMassager; registerArgumentMassager('ttsEngine.onSpeak', function(args, dispatch) { var text = args[0]; var options = args[1]; var requestId = args[2]; var sendTtsEvent = function(event) { chrome.ttsEngine.sendTtsEvent(requestId, event); }; dispatch([text, options, sendTtsEvent]); }); if (!apiBridge) exports.$set('binding', binding.generate()); // Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Custom binding for the webrtcDesktopCapturePrivate API. var binding = apiBridge || require('binding').Binding.create('webrtcDesktopCapturePrivate'); var sendRequest = bindingUtil ? $Function.bind(bindingUtil.sendRequest, bindingUtil) : require('sendRequest').sendRequest; var idGenerator = requireNative('id_generator'); binding.registerCustomHook(function(bindingsAPI) { var apiFunctions = bindingsAPI.apiFunctions; var pendingRequests = {}; function onRequestResult(id, result) { if (id in pendingRequests) { var callback = pendingRequests[id]; delete pendingRequests[id]; callback(result); } } apiFunctions.setHandleRequest('chooseDesktopMedia', function(sources, request, callback) { var id = idGenerator.GetNextId(); pendingRequests[id] = callback; sendRequest('webrtcDesktopCapturePrivate.chooseDesktopMedia', [id, sources, request, $Function.bind(onRequestResult, null, id)], bindingUtil ? undefined : this.definition.parameters, undefined); return id; }); apiFunctions.setHandleRequest('cancelChooseDesktopMedia', function(id) { if (id in pendingRequests) { delete pendingRequests[id]; sendRequest('webrtcDesktopCapturePrivate.cancelChooseDesktopMedia', [id], bindingUtil ? undefined : this.definition.parameters, undefined); } }); }); if (!apiBridge) exports.$set('binding', binding.generate()); // Copyright 2017 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Custom binding for the webrtcLoggingPrivate API. var binding = apiBridge || require('binding').Binding.create('webrtcLoggingPrivate'); var getBindDirectoryEntryCallback = require('fileEntryBindingUtil').getBindDirectoryEntryCallback; binding.registerCustomHook(function(binding, id, contextType) { var apiFunctions = binding.apiFunctions; apiFunctions.setCustomCallback('getLogsDirectory', getBindDirectoryEntryCallback()); }); if (!apiBridge) exports.$set('binding', binding.generate()); // Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Custom binding for the webstore API. var webstoreNatives = requireNative('webstore'); var onInstallStageChanged; var onDownloadProgress; function Installer() { this._pendingInstall = null; } Installer.prototype.install = function(url, onSuccess, onFailure) { if (this._pendingInstall) throw new Error('A Chrome Web Store installation is already pending.'); // With native bindings, these calls go through argument validation, which // sets optional/missing arguments to null. The native webstore bindings // expect either present or undefined, so transform null to undefined. if (url === null) url = undefined; if (onSuccess === null) onSuccess = undefined; if (onFailure === null) onFailure = undefined; if (url !== undefined && typeof url !== 'string') { throw new Error( 'The Chrome Web Store item link URL parameter must be a string.'); } if (onSuccess !== undefined && typeof onSuccess !== 'function') { throw new Error('The success callback parameter must be a function.'); } if (onFailure !== undefined && typeof onFailure !== 'function') { throw new Error('The failure callback parameter must be a function.'); } // Since we call Install() with a bool for if we have listeners, listeners // must be set prior to the inline installation starting (this is also // noted in the Event documentation in // chrome/common/extensions/api/webstore.json). var installId = webstoreNatives.Install( onInstallStageChanged.hasListeners(), onDownloadProgress.hasListeners(), url, onSuccess, onFailure); if (installId !== undefined) { this._pendingInstall = { installId: installId, onSuccess: onSuccess, onFailure: onFailure }; } }; Installer.prototype.onInstallResponse = function(installId, success, error, resultCode) { var pendingInstall = this._pendingInstall; if (!pendingInstall || pendingInstall.installId != installId) { // TODO(kalman): should this be an error? return; } try { if (success && pendingInstall.onSuccess) pendingInstall.onSuccess(); else if (!success && pendingInstall.onFailure) pendingInstall.onFailure(error, resultCode); } catch (e) { console.error('Exception in chrome.webstore.install response handler: ' + e.stack); } finally { this._pendingInstall = null; } }; Installer.prototype.onInstallStageChanged = function(installStage) { onInstallStageChanged.dispatch(installStage); }; Installer.prototype.onDownloadProgress = function(progress) { onDownloadProgress.dispatch(progress); }; var installer = new Installer(); if (apiBridge) { apiBridge.registerCustomHook(function(api) { api.apiFunctions.setHandleRequest('install', function(url, onSuccess, onFailure) { installer.install(url, onSuccess, onFailure); }); onInstallStageChanged = api.compiledApi.onInstallStageChanged; onDownloadProgress = api.compiledApi.onDownloadProgress; }); } else { var Event = require('event_bindings').Event; onInstallStageChanged = new Event(null, [{name: 'stage', type: 'string'}], {unmanaged: true}); onDownloadProgress = new Event(null, [{name: 'progress', type: 'number'}], {unmanaged: true}); var chromeWebstore = { install: function (url, onSuccess, onFailure) { installer.install(url, onSuccess, onFailure); }, onInstallStageChanged: onInstallStageChanged, onDownloadProgress: onDownloadProgress, }; exports.$set('binding', chromeWebstore); } // Called by webstore_bindings.cc. exports.$set('onInstallResponse', $Function.bind(Installer.prototype.onInstallResponse, installer)); exports.$set('onInstallStageChanged', $Function.bind(Installer.prototype.onInstallStageChanged, installer)); exports.$set('onDownloadProgress', $Function.bind(Installer.prototype.onDownloadProgress, installer)); // Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. 'use strict'; (function() { var mojomId = 'chrome/common/media_router/mojo/media_controller.mojom'; if (mojo.internal.isMojomLoaded(mojomId)) { console.warn('The following mojom is loaded multiple times: ' + mojomId); return; } mojo.internal.markMojomLoaded(mojomId); var bindings = mojo; var associatedBindings = mojo; var codec = mojo.internal; var validator = mojo.internal; var exports = mojo.internal.exposeNamespace('mediaRouter.mojom'); var media_status$ = mojo.internal.exposeNamespace('mediaRouter.mojom'); if (mojo.config.autoLoadMojomDeps) { mojo.internal.loadMojomIfNecessary( 'chrome/common/media_router/mojo/media_status.mojom', 'media_status.mojom.js'); } var time$ = mojo.internal.exposeNamespace('mojo.common.mojom'); if (mojo.config.autoLoadMojomDeps) { mojo.internal.loadMojomIfNecessary( 'mojo/common/time.mojom', '../../../../mojo/common/time.mojom.js'); } function MediaController_Play_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaController_Play_Params.prototype.initDefaults_ = function() { }; MediaController_Play_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaController_Play_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 8} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaController_Play_Params.encodedSize = codec.kStructHeaderSize + 0; MediaController_Play_Params.decode = function(decoder) { var packed; var val = new MediaController_Play_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); return val; }; MediaController_Play_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaController_Play_Params.encodedSize); encoder.writeUint32(0); }; function MediaController_Pause_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaController_Pause_Params.prototype.initDefaults_ = function() { }; MediaController_Pause_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaController_Pause_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 8} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaController_Pause_Params.encodedSize = codec.kStructHeaderSize + 0; MediaController_Pause_Params.decode = function(decoder) { var packed; var val = new MediaController_Pause_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); return val; }; MediaController_Pause_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaController_Pause_Params.encodedSize); encoder.writeUint32(0); }; function MediaController_SetMute_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaController_SetMute_Params.prototype.initDefaults_ = function() { this.mute = false; }; MediaController_SetMute_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaController_SetMute_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaController_SetMute_Params.encodedSize = codec.kStructHeaderSize + 8; MediaController_SetMute_Params.decode = function(decoder) { var packed; var val = new MediaController_SetMute_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); packed = decoder.readUint8(); val.mute = (packed >> 0) & 1 ? true : false; decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); return val; }; MediaController_SetMute_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaController_SetMute_Params.encodedSize); encoder.writeUint32(0); packed = 0; packed |= (val.mute & 1) << 0 encoder.writeUint8(packed); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); }; function MediaController_SetVolume_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaController_SetVolume_Params.prototype.initDefaults_ = function() { this.volume = 0; }; MediaController_SetVolume_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaController_SetVolume_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaController_SetVolume_Params.encodedSize = codec.kStructHeaderSize + 8; MediaController_SetVolume_Params.decode = function(decoder) { var packed; var val = new MediaController_SetVolume_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.volume = decoder.decodeStruct(codec.Float); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); return val; }; MediaController_SetVolume_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaController_SetVolume_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.Float, val.volume); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); }; function MediaController_Seek_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaController_Seek_Params.prototype.initDefaults_ = function() { this.time = null; }; MediaController_Seek_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaController_Seek_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaController_Seek_Params.time err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 0, time$.TimeDelta, false); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaController_Seek_Params.encodedSize = codec.kStructHeaderSize + 8; MediaController_Seek_Params.decode = function(decoder) { var packed; var val = new MediaController_Seek_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.time = decoder.decodeStructPointer(time$.TimeDelta); return val; }; MediaController_Seek_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaController_Seek_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStructPointer(time$.TimeDelta, val.time); }; function MediaController_ConnectHangoutsMediaRouteController_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaController_ConnectHangoutsMediaRouteController_Params.prototype.initDefaults_ = function() { this.controllerRequest = new bindings.InterfaceRequest(); }; MediaController_ConnectHangoutsMediaRouteController_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaController_ConnectHangoutsMediaRouteController_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaController_ConnectHangoutsMediaRouteController_Params.controllerRequest err = messageValidator.validateInterfaceRequest(offset + codec.kStructHeaderSize + 0, false) if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaController_ConnectHangoutsMediaRouteController_Params.encodedSize = codec.kStructHeaderSize + 8; MediaController_ConnectHangoutsMediaRouteController_Params.decode = function(decoder) { var packed; var val = new MediaController_ConnectHangoutsMediaRouteController_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.controllerRequest = decoder.decodeStruct(codec.InterfaceRequest); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); return val; }; MediaController_ConnectHangoutsMediaRouteController_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaController_ConnectHangoutsMediaRouteController_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.InterfaceRequest, val.controllerRequest); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); }; function HangoutsMediaRouteController_SetLocalPresent_Params(values) { this.initDefaults_(); this.initFields_(values); } HangoutsMediaRouteController_SetLocalPresent_Params.prototype.initDefaults_ = function() { this.localPresent = false; }; HangoutsMediaRouteController_SetLocalPresent_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; HangoutsMediaRouteController_SetLocalPresent_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; HangoutsMediaRouteController_SetLocalPresent_Params.encodedSize = codec.kStructHeaderSize + 8; HangoutsMediaRouteController_SetLocalPresent_Params.decode = function(decoder) { var packed; var val = new HangoutsMediaRouteController_SetLocalPresent_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); packed = decoder.readUint8(); val.localPresent = (packed >> 0) & 1 ? true : false; decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); return val; }; HangoutsMediaRouteController_SetLocalPresent_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(HangoutsMediaRouteController_SetLocalPresent_Params.encodedSize); encoder.writeUint32(0); packed = 0; packed |= (val.localPresent & 1) << 0 encoder.writeUint8(packed); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); }; var kMediaController_Play_Name = 1707544988; var kMediaController_Pause_Name = 425314644; var kMediaController_SetMute_Name = 1576739997; var kMediaController_SetVolume_Name = 1452905642; var kMediaController_Seek_Name = 206977129; var kMediaController_ConnectHangoutsMediaRouteController_Name = 257503576; function MediaControllerPtr(handleOrPtrInfo) { this.ptr = new bindings.InterfacePtrController(MediaController, handleOrPtrInfo); } function MediaControllerAssociatedPtr(associatedInterfacePtrInfo) { this.ptr = new associatedBindings.AssociatedInterfacePtrController( MediaController, associatedInterfacePtrInfo); } MediaControllerAssociatedPtr.prototype = Object.create(MediaControllerPtr.prototype); MediaControllerAssociatedPtr.prototype.constructor = MediaControllerAssociatedPtr; function MediaControllerProxy(receiver) { this.receiver_ = receiver; } MediaControllerPtr.prototype.play = function() { return MediaControllerProxy.prototype.play .apply(this.ptr.getProxy(), arguments); }; MediaControllerProxy.prototype.play = function() { var params = new MediaController_Play_Params(); var builder = new codec.MessageV0Builder( kMediaController_Play_Name, codec.align(MediaController_Play_Params.encodedSize)); builder.encodeStruct(MediaController_Play_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; MediaControllerPtr.prototype.pause = function() { return MediaControllerProxy.prototype.pause .apply(this.ptr.getProxy(), arguments); }; MediaControllerProxy.prototype.pause = function() { var params = new MediaController_Pause_Params(); var builder = new codec.MessageV0Builder( kMediaController_Pause_Name, codec.align(MediaController_Pause_Params.encodedSize)); builder.encodeStruct(MediaController_Pause_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; MediaControllerPtr.prototype.setMute = function() { return MediaControllerProxy.prototype.setMute .apply(this.ptr.getProxy(), arguments); }; MediaControllerProxy.prototype.setMute = function(mute) { var params = new MediaController_SetMute_Params(); params.mute = mute; var builder = new codec.MessageV0Builder( kMediaController_SetMute_Name, codec.align(MediaController_SetMute_Params.encodedSize)); builder.encodeStruct(MediaController_SetMute_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; MediaControllerPtr.prototype.setVolume = function() { return MediaControllerProxy.prototype.setVolume .apply(this.ptr.getProxy(), arguments); }; MediaControllerProxy.prototype.setVolume = function(volume) { var params = new MediaController_SetVolume_Params(); params.volume = volume; var builder = new codec.MessageV0Builder( kMediaController_SetVolume_Name, codec.align(MediaController_SetVolume_Params.encodedSize)); builder.encodeStruct(MediaController_SetVolume_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; MediaControllerPtr.prototype.seek = function() { return MediaControllerProxy.prototype.seek .apply(this.ptr.getProxy(), arguments); }; MediaControllerProxy.prototype.seek = function(time) { var params = new MediaController_Seek_Params(); params.time = time; var builder = new codec.MessageV0Builder( kMediaController_Seek_Name, codec.align(MediaController_Seek_Params.encodedSize)); builder.encodeStruct(MediaController_Seek_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; MediaControllerPtr.prototype.connectHangoutsMediaRouteController = function() { return MediaControllerProxy.prototype.connectHangoutsMediaRouteController .apply(this.ptr.getProxy(), arguments); }; MediaControllerProxy.prototype.connectHangoutsMediaRouteController = function(controllerRequest) { var params = new MediaController_ConnectHangoutsMediaRouteController_Params(); params.controllerRequest = controllerRequest; var builder = new codec.MessageV0Builder( kMediaController_ConnectHangoutsMediaRouteController_Name, codec.align(MediaController_ConnectHangoutsMediaRouteController_Params.encodedSize)); builder.encodeStruct(MediaController_ConnectHangoutsMediaRouteController_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; function MediaControllerStub(delegate) { this.delegate_ = delegate; } MediaControllerStub.prototype.play = function() { return this.delegate_ && this.delegate_.play && this.delegate_.play(); } MediaControllerStub.prototype.pause = function() { return this.delegate_ && this.delegate_.pause && this.delegate_.pause(); } MediaControllerStub.prototype.setMute = function(mute) { return this.delegate_ && this.delegate_.setMute && this.delegate_.setMute(mute); } MediaControllerStub.prototype.setVolume = function(volume) { return this.delegate_ && this.delegate_.setVolume && this.delegate_.setVolume(volume); } MediaControllerStub.prototype.seek = function(time) { return this.delegate_ && this.delegate_.seek && this.delegate_.seek(time); } MediaControllerStub.prototype.connectHangoutsMediaRouteController = function(controllerRequest) { return this.delegate_ && this.delegate_.connectHangoutsMediaRouteController && this.delegate_.connectHangoutsMediaRouteController(controllerRequest); } MediaControllerStub.prototype.accept = function(message) { var reader = new codec.MessageReader(message); switch (reader.messageName) { case kMediaController_Play_Name: var params = reader.decodeStruct(MediaController_Play_Params); this.play(); return true; case kMediaController_Pause_Name: var params = reader.decodeStruct(MediaController_Pause_Params); this.pause(); return true; case kMediaController_SetMute_Name: var params = reader.decodeStruct(MediaController_SetMute_Params); this.setMute(params.mute); return true; case kMediaController_SetVolume_Name: var params = reader.decodeStruct(MediaController_SetVolume_Params); this.setVolume(params.volume); return true; case kMediaController_Seek_Name: var params = reader.decodeStruct(MediaController_Seek_Params); this.seek(params.time); return true; case kMediaController_ConnectHangoutsMediaRouteController_Name: var params = reader.decodeStruct(MediaController_ConnectHangoutsMediaRouteController_Params); this.connectHangoutsMediaRouteController(params.controllerRequest); return true; default: return false; } }; MediaControllerStub.prototype.acceptWithResponder = function(message, responder) { var reader = new codec.MessageReader(message); switch (reader.messageName) { default: return false; } }; function validateMediaControllerRequest(messageValidator) { var message = messageValidator.message; var paramsClass = null; switch (message.getName()) { case kMediaController_Play_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = MediaController_Play_Params; break; case kMediaController_Pause_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = MediaController_Pause_Params; break; case kMediaController_SetMute_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = MediaController_SetMute_Params; break; case kMediaController_SetVolume_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = MediaController_SetVolume_Params; break; case kMediaController_Seek_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = MediaController_Seek_Params; break; case kMediaController_ConnectHangoutsMediaRouteController_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = MediaController_ConnectHangoutsMediaRouteController_Params; break; } if (paramsClass === null) return validator.validationError.NONE; return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes()); } function validateMediaControllerResponse(messageValidator) { return validator.validationError.NONE; } var MediaController = { name: 'media_router::mojom::MediaController', kVersion: 0, ptrClass: MediaControllerPtr, proxyClass: MediaControllerProxy, stubClass: MediaControllerStub, validateRequest: validateMediaControllerRequest, validateResponse: null, }; MediaControllerStub.prototype.validator = validateMediaControllerRequest; MediaControllerProxy.prototype.validator = null; var kHangoutsMediaRouteController_SetLocalPresent_Name = 804107141; function HangoutsMediaRouteControllerPtr(handleOrPtrInfo) { this.ptr = new bindings.InterfacePtrController(HangoutsMediaRouteController, handleOrPtrInfo); } function HangoutsMediaRouteControllerAssociatedPtr(associatedInterfacePtrInfo) { this.ptr = new associatedBindings.AssociatedInterfacePtrController( HangoutsMediaRouteController, associatedInterfacePtrInfo); } HangoutsMediaRouteControllerAssociatedPtr.prototype = Object.create(HangoutsMediaRouteControllerPtr.prototype); HangoutsMediaRouteControllerAssociatedPtr.prototype.constructor = HangoutsMediaRouteControllerAssociatedPtr; function HangoutsMediaRouteControllerProxy(receiver) { this.receiver_ = receiver; } HangoutsMediaRouteControllerPtr.prototype.setLocalPresent = function() { return HangoutsMediaRouteControllerProxy.prototype.setLocalPresent .apply(this.ptr.getProxy(), arguments); }; HangoutsMediaRouteControllerProxy.prototype.setLocalPresent = function(localPresent) { var params = new HangoutsMediaRouteController_SetLocalPresent_Params(); params.localPresent = localPresent; var builder = new codec.MessageV0Builder( kHangoutsMediaRouteController_SetLocalPresent_Name, codec.align(HangoutsMediaRouteController_SetLocalPresent_Params.encodedSize)); builder.encodeStruct(HangoutsMediaRouteController_SetLocalPresent_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; function HangoutsMediaRouteControllerStub(delegate) { this.delegate_ = delegate; } HangoutsMediaRouteControllerStub.prototype.setLocalPresent = function(localPresent) { return this.delegate_ && this.delegate_.setLocalPresent && this.delegate_.setLocalPresent(localPresent); } HangoutsMediaRouteControllerStub.prototype.accept = function(message) { var reader = new codec.MessageReader(message); switch (reader.messageName) { case kHangoutsMediaRouteController_SetLocalPresent_Name: var params = reader.decodeStruct(HangoutsMediaRouteController_SetLocalPresent_Params); this.setLocalPresent(params.localPresent); return true; default: return false; } }; HangoutsMediaRouteControllerStub.prototype.acceptWithResponder = function(message, responder) { var reader = new codec.MessageReader(message); switch (reader.messageName) { default: return false; } }; function validateHangoutsMediaRouteControllerRequest(messageValidator) { var message = messageValidator.message; var paramsClass = null; switch (message.getName()) { case kHangoutsMediaRouteController_SetLocalPresent_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = HangoutsMediaRouteController_SetLocalPresent_Params; break; } if (paramsClass === null) return validator.validationError.NONE; return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes()); } function validateHangoutsMediaRouteControllerResponse(messageValidator) { return validator.validationError.NONE; } var HangoutsMediaRouteController = { name: 'media_router::mojom::HangoutsMediaRouteController', kVersion: 0, ptrClass: HangoutsMediaRouteControllerPtr, proxyClass: HangoutsMediaRouteControllerProxy, stubClass: HangoutsMediaRouteControllerStub, validateRequest: validateHangoutsMediaRouteControllerRequest, validateResponse: null, }; HangoutsMediaRouteControllerStub.prototype.validator = validateHangoutsMediaRouteControllerRequest; HangoutsMediaRouteControllerProxy.prototype.validator = null; exports.MediaController = MediaController; exports.MediaControllerPtr = MediaControllerPtr; exports.MediaControllerAssociatedPtr = MediaControllerAssociatedPtr; exports.HangoutsMediaRouteController = HangoutsMediaRouteController; exports.HangoutsMediaRouteControllerPtr = HangoutsMediaRouteControllerPtr; exports.HangoutsMediaRouteControllerAssociatedPtr = HangoutsMediaRouteControllerAssociatedPtr; })();// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. 'use strict'; (function() { var mojomId = 'chrome/common/media_router/mojo/media_router.mojom'; if (mojo.internal.isMojomLoaded(mojomId)) { console.warn('The following mojom is loaded multiple times: ' + mojomId); return; } mojo.internal.markMojomLoaded(mojomId); var bindings = mojo; var associatedBindings = mojo; var codec = mojo.internal; var validator = mojo.internal; var exports = mojo.internal.exposeNamespace('mediaRouter.mojom'); var media_controller$ = mojo.internal.exposeNamespace('mediaRouter.mojom'); if (mojo.config.autoLoadMojomDeps) { mojo.internal.loadMojomIfNecessary( 'chrome/common/media_router/mojo/media_controller.mojom', 'media_controller.mojom.js'); } var media_status$ = mojo.internal.exposeNamespace('mediaRouter.mojom'); if (mojo.config.autoLoadMojomDeps) { mojo.internal.loadMojomIfNecessary( 'chrome/common/media_router/mojo/media_status.mojom', 'media_status.mojom.js'); } var mirror_service_remoting$ = mojo.internal.exposeNamespace('media.mojom'); if (mojo.config.autoLoadMojomDeps) { mojo.internal.loadMojomIfNecessary( 'media/mojo/interfaces/mirror_service_remoting.mojom', '../../../../media/mojo/interfaces/mirror_service_remoting.mojom.js'); } var time$ = mojo.internal.exposeNamespace('mojo.common.mojom'); if (mojo.config.autoLoadMojomDeps) { mojo.internal.loadMojomIfNecessary( 'mojo/common/time.mojom', '../../../../mojo/common/time.mojom.js'); } var ip_address$ = mojo.internal.exposeNamespace('net.interfaces'); if (mojo.config.autoLoadMojomDeps) { mojo.internal.loadMojomIfNecessary( 'net/interfaces/ip_address.mojom', '../../../../net/interfaces/ip_address.mojom.js'); } var ip_endpoint$ = mojo.internal.exposeNamespace('net.interfaces'); if (mojo.config.autoLoadMojomDeps) { mojo.internal.loadMojomIfNecessary( 'net/interfaces/ip_endpoint.mojom', '../../../../net/interfaces/ip_endpoint.mojom.js'); } var origin$ = mojo.internal.exposeNamespace('url.mojom'); if (mojo.config.autoLoadMojomDeps) { mojo.internal.loadMojomIfNecessary( 'url/mojo/origin.mojom', '../../../../url/mojo/origin.mojom.js'); } var url$ = mojo.internal.exposeNamespace('url.mojom'); if (mojo.config.autoLoadMojomDeps) { mojo.internal.loadMojomIfNecessary( 'url/mojo/url.mojom', '../../../../url/mojo/url.mojom.js'); } var SinkIconType = {}; SinkIconType.CAST = 0; SinkIconType.CAST_AUDIO_GROUP = SinkIconType.CAST + 1; SinkIconType.CAST_AUDIO = SinkIconType.CAST_AUDIO_GROUP + 1; SinkIconType.MEETING = SinkIconType.CAST_AUDIO + 1; SinkIconType.HANGOUT = SinkIconType.MEETING + 1; SinkIconType.EDUCATION = SinkIconType.HANGOUT + 1; SinkIconType.WIRED_DISPLAY = SinkIconType.EDUCATION + 1; SinkIconType.GENERIC = SinkIconType.WIRED_DISPLAY + 1; SinkIconType.isKnownEnumValue = function(value) { switch (value) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: return true; } return false; }; SinkIconType.validate = function(enumValue) { var isExtensible = false; if (isExtensible || this.isKnownEnumValue(enumValue)) return validator.validationError.NONE; return validator.validationError.UNKNOWN_ENUM_VALUE; }; var RouteControllerType = {}; RouteControllerType.kNone = 0; RouteControllerType.kGeneric = RouteControllerType.kNone + 1; RouteControllerType.kHangouts = RouteControllerType.kGeneric + 1; RouteControllerType.kMirroring = RouteControllerType.kHangouts + 1; RouteControllerType.isKnownEnumValue = function(value) { switch (value) { case 0: case 1: case 2: case 3: return true; } return false; }; RouteControllerType.validate = function(enumValue) { var isExtensible = false; if (isExtensible || this.isKnownEnumValue(enumValue)) return validator.validationError.NONE; return validator.validationError.UNKNOWN_ENUM_VALUE; }; var RouteRequestResultCode = {}; RouteRequestResultCode.UNKNOWN_ERROR = 0; RouteRequestResultCode.OK = RouteRequestResultCode.UNKNOWN_ERROR + 1; RouteRequestResultCode.TIMED_OUT = RouteRequestResultCode.OK + 1; RouteRequestResultCode.ROUTE_NOT_FOUND = RouteRequestResultCode.TIMED_OUT + 1; RouteRequestResultCode.SINK_NOT_FOUND = RouteRequestResultCode.ROUTE_NOT_FOUND + 1; RouteRequestResultCode.INVALID_ORIGIN = RouteRequestResultCode.SINK_NOT_FOUND + 1; RouteRequestResultCode.INCOGNITO_MISMATCH = RouteRequestResultCode.INVALID_ORIGIN + 1; RouteRequestResultCode.NO_SUPPORTED_PROVIDER = RouteRequestResultCode.INCOGNITO_MISMATCH + 1; RouteRequestResultCode.CANCELLED = RouteRequestResultCode.NO_SUPPORTED_PROVIDER + 1; RouteRequestResultCode.isKnownEnumValue = function(value) { switch (value) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: return true; } return false; }; RouteRequestResultCode.validate = function(enumValue) { var isExtensible = false; if (isExtensible || this.isKnownEnumValue(enumValue)) return validator.validationError.NONE; return validator.validationError.UNKNOWN_ENUM_VALUE; }; function MediaSink(values) { this.initDefaults_(); this.initFields_(values); } MediaSink.prototype.initDefaults_ = function() { this.sinkId = null; this.name = null; this.description = null; this.domain = null; this.iconType = 0; this.providerId = 0; this.extraData = null; }; MediaSink.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaSink.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 64} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaSink.sinkId err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false) if (err !== validator.validationError.NONE) return err; // validate MediaSink.name err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false) if (err !== validator.validationError.NONE) return err; // validate MediaSink.description err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 16, true) if (err !== validator.validationError.NONE) return err; // validate MediaSink.domain err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 24, true) if (err !== validator.validationError.NONE) return err; // validate MediaSink.iconType err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 32, SinkIconType); if (err !== validator.validationError.NONE) return err; // validate MediaSink.providerId err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 36, MediaRouteProvider.Id); if (err !== validator.validationError.NONE) return err; // validate MediaSink.extraData err = messageValidator.validateUnion(offset + codec.kStructHeaderSize + 40, MediaSinkExtraData, true); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaSink.encodedSize = codec.kStructHeaderSize + 56; MediaSink.decode = function(decoder) { var packed; var val = new MediaSink(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.sinkId = decoder.decodeStruct(codec.String); val.name = decoder.decodeStruct(codec.String); val.description = decoder.decodeStruct(codec.NullableString); val.domain = decoder.decodeStruct(codec.NullableString); val.iconType = decoder.decodeStruct(codec.Int32); val.providerId = decoder.decodeStruct(codec.Int32); val.extraData = decoder.decodeStruct(MediaSinkExtraData); return val; }; MediaSink.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaSink.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.String, val.sinkId); encoder.encodeStruct(codec.String, val.name); encoder.encodeStruct(codec.NullableString, val.description); encoder.encodeStruct(codec.NullableString, val.domain); encoder.encodeStruct(codec.Int32, val.iconType); encoder.encodeStruct(codec.Int32, val.providerId); encoder.encodeStruct(MediaSinkExtraData, val.extraData); }; function DialMediaSink(values) { this.initDefaults_(); this.initFields_(values); } DialMediaSink.prototype.initDefaults_ = function() { this.ipAddress = null; this.modelName = null; this.appUrl = null; }; DialMediaSink.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; DialMediaSink.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 32} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate DialMediaSink.ipAddress err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 0, ip_address$.IPAddress, false); if (err !== validator.validationError.NONE) return err; // validate DialMediaSink.modelName err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false) if (err !== validator.validationError.NONE) return err; // validate DialMediaSink.appUrl err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 16, url$.Url, false); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; DialMediaSink.encodedSize = codec.kStructHeaderSize + 24; DialMediaSink.decode = function(decoder) { var packed; var val = new DialMediaSink(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.ipAddress = decoder.decodeStructPointer(ip_address$.IPAddress); val.modelName = decoder.decodeStruct(codec.String); val.appUrl = decoder.decodeStructPointer(url$.Url); return val; }; DialMediaSink.encode = function(encoder, val) { var packed; encoder.writeUint32(DialMediaSink.encodedSize); encoder.writeUint32(0); encoder.encodeStructPointer(ip_address$.IPAddress, val.ipAddress); encoder.encodeStruct(codec.String, val.modelName); encoder.encodeStructPointer(url$.Url, val.appUrl); }; function CastMediaSink(values) { this.initDefaults_(); this.initFields_(values); } CastMediaSink.prototype.initDefaults_ = function() { this.ipEndpoint = null; this.modelName = null; this.capabilities = 0; this.castChannelId = 0; }; CastMediaSink.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; CastMediaSink.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 32} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate CastMediaSink.ipEndpoint err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 0, ip_endpoint$.IPEndPoint, false); if (err !== validator.validationError.NONE) return err; // validate CastMediaSink.modelName err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false) if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; CastMediaSink.encodedSize = codec.kStructHeaderSize + 24; CastMediaSink.decode = function(decoder) { var packed; var val = new CastMediaSink(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.ipEndpoint = decoder.decodeStructPointer(ip_endpoint$.IPEndPoint); val.modelName = decoder.decodeStruct(codec.String); val.capabilities = decoder.decodeStruct(codec.Uint8); decoder.skip(1); decoder.skip(1); decoder.skip(1); val.castChannelId = decoder.decodeStruct(codec.Int32); return val; }; CastMediaSink.encode = function(encoder, val) { var packed; encoder.writeUint32(CastMediaSink.encodedSize); encoder.writeUint32(0); encoder.encodeStructPointer(ip_endpoint$.IPEndPoint, val.ipEndpoint); encoder.encodeStruct(codec.String, val.modelName); encoder.encodeStruct(codec.Uint8, val.capabilities); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.encodeStruct(codec.Int32, val.castChannelId); }; function MediaRoute(values) { this.initDefaults_(); this.initFields_(values); } MediaRoute.prototype.initDefaults_ = function() { this.mediaRouteId = null; this.presentationId = null; this.mediaSource = null; this.mediaSinkId = null; this.description = null; this.isLocal = false; this.forDisplay = false; this.isIncognito = false; this.isLocalPresentation = false; this.controllerType = 0; }; MediaRoute.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRoute.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 56} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRoute.mediaRouteId err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false) if (err !== validator.validationError.NONE) return err; // validate MediaRoute.presentationId err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false) if (err !== validator.validationError.NONE) return err; // validate MediaRoute.mediaSource err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 16, true) if (err !== validator.validationError.NONE) return err; // validate MediaRoute.mediaSinkId err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 24, false) if (err !== validator.validationError.NONE) return err; // validate MediaRoute.description err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 32, false) if (err !== validator.validationError.NONE) return err; // validate MediaRoute.controllerType err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 44, RouteControllerType); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRoute.encodedSize = codec.kStructHeaderSize + 48; MediaRoute.decode = function(decoder) { var packed; var val = new MediaRoute(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.mediaRouteId = decoder.decodeStruct(codec.String); val.presentationId = decoder.decodeStruct(codec.String); val.mediaSource = decoder.decodeStruct(codec.NullableString); val.mediaSinkId = decoder.decodeStruct(codec.String); val.description = decoder.decodeStruct(codec.String); packed = decoder.readUint8(); val.isLocal = (packed >> 0) & 1 ? true : false; val.forDisplay = (packed >> 1) & 1 ? true : false; val.isIncognito = (packed >> 2) & 1 ? true : false; val.isLocalPresentation = (packed >> 3) & 1 ? true : false; decoder.skip(1); decoder.skip(1); decoder.skip(1); val.controllerType = decoder.decodeStruct(codec.Int32); return val; }; MediaRoute.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRoute.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.String, val.mediaRouteId); encoder.encodeStruct(codec.String, val.presentationId); encoder.encodeStruct(codec.NullableString, val.mediaSource); encoder.encodeStruct(codec.String, val.mediaSinkId); encoder.encodeStruct(codec.String, val.description); packed = 0; packed |= (val.isLocal & 1) << 0 packed |= (val.forDisplay & 1) << 1 packed |= (val.isIncognito & 1) << 2 packed |= (val.isLocalPresentation & 1) << 3 encoder.writeUint8(packed); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.encodeStruct(codec.Int32, val.controllerType); }; function Issue(values) { this.initDefaults_(); this.initFields_(values); } Issue.Severity = {}; Issue.Severity.FATAL = 0; Issue.Severity.WARNING = Issue.Severity.FATAL + 1; Issue.Severity.NOTIFICATION = Issue.Severity.WARNING + 1; Issue.Severity.isKnownEnumValue = function(value) { switch (value) { case 0: case 1: case 2: return true; } return false; }; Issue.Severity.validate = function(enumValue) { var isExtensible = false; if (isExtensible || this.isKnownEnumValue(enumValue)) return validator.validationError.NONE; return validator.validationError.UNKNOWN_ENUM_VALUE; }; Issue.ActionType = {}; Issue.ActionType.DISMISS = 0; Issue.ActionType.LEARN_MORE = Issue.ActionType.DISMISS + 1; Issue.ActionType.isKnownEnumValue = function(value) { switch (value) { case 0: case 1: return true; } return false; }; Issue.ActionType.validate = function(enumValue) { var isExtensible = false; if (isExtensible || this.isKnownEnumValue(enumValue)) return validator.validationError.NONE; return validator.validationError.UNKNOWN_ENUM_VALUE; }; Issue.prototype.initDefaults_ = function() { this.routeId = null; this.severity = 0; this.isBlocking = false; this.title = null; this.message = null; this.defaultAction = 0; this.helpPageId = 0; this.secondaryActions = null; }; Issue.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; Issue.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 56} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate Issue.routeId err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, true) if (err !== validator.validationError.NONE) return err; // validate Issue.severity err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 8, Issue.Severity); if (err !== validator.validationError.NONE) return err; // validate Issue.title err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 16, false) if (err !== validator.validationError.NONE) return err; // validate Issue.message err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 24, true) if (err !== validator.validationError.NONE) return err; // validate Issue.defaultAction err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 32, Issue.ActionType); if (err !== validator.validationError.NONE) return err; // validate Issue.secondaryActions err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 40, 4, new codec.Enum(Issue.ActionType), false, [0], 0); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; Issue.encodedSize = codec.kStructHeaderSize + 48; Issue.decode = function(decoder) { var packed; var val = new Issue(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.routeId = decoder.decodeStruct(codec.NullableString); val.severity = decoder.decodeStruct(codec.Int32); packed = decoder.readUint8(); val.isBlocking = (packed >> 0) & 1 ? true : false; decoder.skip(1); decoder.skip(1); decoder.skip(1); val.title = decoder.decodeStruct(codec.String); val.message = decoder.decodeStruct(codec.NullableString); val.defaultAction = decoder.decodeStruct(codec.Int32); val.helpPageId = decoder.decodeStruct(codec.Int32); val.secondaryActions = decoder.decodeArrayPointer(new codec.Enum(Issue.ActionType)); return val; }; Issue.encode = function(encoder, val) { var packed; encoder.writeUint32(Issue.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.NullableString, val.routeId); encoder.encodeStruct(codec.Int32, val.severity); packed = 0; packed |= (val.isBlocking & 1) << 0 encoder.writeUint8(packed); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.encodeStruct(codec.String, val.title); encoder.encodeStruct(codec.NullableString, val.message); encoder.encodeStruct(codec.Int32, val.defaultAction); encoder.encodeStruct(codec.Int32, val.helpPageId); encoder.encodeArrayPointer(new codec.Enum(Issue.ActionType), val.secondaryActions); }; function RouteMessage(values) { this.initDefaults_(); this.initFields_(values); } RouteMessage.Type = {}; RouteMessage.Type.TEXT = 0; RouteMessage.Type.BINARY = RouteMessage.Type.TEXT + 1; RouteMessage.Type.isKnownEnumValue = function(value) { switch (value) { case 0: case 1: return true; } return false; }; RouteMessage.Type.validate = function(enumValue) { var isExtensible = false; if (isExtensible || this.isKnownEnumValue(enumValue)) return validator.validationError.NONE; return validator.validationError.UNKNOWN_ENUM_VALUE; }; RouteMessage.prototype.initDefaults_ = function() { this.type = 0; this.message = null; this.data = null; }; RouteMessage.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; RouteMessage.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 32} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate RouteMessage.type err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 0, RouteMessage.Type); if (err !== validator.validationError.NONE) return err; // validate RouteMessage.message err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, true) if (err !== validator.validationError.NONE) return err; // validate RouteMessage.data err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 16, 1, codec.Uint8, true, [0], 0); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; RouteMessage.encodedSize = codec.kStructHeaderSize + 24; RouteMessage.decode = function(decoder) { var packed; var val = new RouteMessage(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.type = decoder.decodeStruct(codec.Int32); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); val.message = decoder.decodeStruct(codec.NullableString); val.data = decoder.decodeArrayPointer(codec.Uint8); return val; }; RouteMessage.encode = function(encoder, val) { var packed; encoder.writeUint32(RouteMessage.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.Int32, val.type); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.encodeStruct(codec.NullableString, val.message); encoder.encodeArrayPointer(codec.Uint8, val.data); }; function SinkSearchCriteria(values) { this.initDefaults_(); this.initFields_(values); } SinkSearchCriteria.prototype.initDefaults_ = function() { this.input = null; this.domain = null; }; SinkSearchCriteria.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; SinkSearchCriteria.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 24} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate SinkSearchCriteria.input err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false) if (err !== validator.validationError.NONE) return err; // validate SinkSearchCriteria.domain err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false) if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; SinkSearchCriteria.encodedSize = codec.kStructHeaderSize + 16; SinkSearchCriteria.decode = function(decoder) { var packed; var val = new SinkSearchCriteria(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.input = decoder.decodeStruct(codec.String); val.domain = decoder.decodeStruct(codec.String); return val; }; SinkSearchCriteria.encode = function(encoder, val) { var packed; encoder.writeUint32(SinkSearchCriteria.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.String, val.input); encoder.encodeStruct(codec.String, val.domain); }; function MediaRouteProviderConfig(values) { this.initDefaults_(); this.initFields_(values); } MediaRouteProviderConfig.prototype.initDefaults_ = function() { this.enableDialDiscovery = false; this.enableCastDiscovery = false; }; MediaRouteProviderConfig.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouteProviderConfig.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouteProviderConfig.encodedSize = codec.kStructHeaderSize + 8; MediaRouteProviderConfig.decode = function(decoder) { var packed; var val = new MediaRouteProviderConfig(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); packed = decoder.readUint8(); val.enableDialDiscovery = (packed >> 0) & 1 ? true : false; val.enableCastDiscovery = (packed >> 1) & 1 ? true : false; decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); return val; }; MediaRouteProviderConfig.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouteProviderConfig.encodedSize); encoder.writeUint32(0); packed = 0; packed |= (val.enableDialDiscovery & 1) << 0 packed |= (val.enableCastDiscovery & 1) << 1 encoder.writeUint8(packed); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); }; function MediaRouteProvider_CreateRoute_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaRouteProvider_CreateRoute_Params.prototype.initDefaults_ = function() { this.mediaSource = null; this.sinkId = null; this.originalPresentationId = null; this.origin = null; this.tabId = 0; this.incognito = false; this.timeout = null; }; MediaRouteProvider_CreateRoute_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouteProvider_CreateRoute_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 56} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_CreateRoute_Params.mediaSource err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false) if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_CreateRoute_Params.sinkId err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false) if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_CreateRoute_Params.originalPresentationId err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 16, false) if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_CreateRoute_Params.origin err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 24, origin$.Origin, false); if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_CreateRoute_Params.timeout err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 40, time$.TimeDelta, false); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouteProvider_CreateRoute_Params.encodedSize = codec.kStructHeaderSize + 48; MediaRouteProvider_CreateRoute_Params.decode = function(decoder) { var packed; var val = new MediaRouteProvider_CreateRoute_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.mediaSource = decoder.decodeStruct(codec.String); val.sinkId = decoder.decodeStruct(codec.String); val.originalPresentationId = decoder.decodeStruct(codec.String); val.origin = decoder.decodeStructPointer(origin$.Origin); val.tabId = decoder.decodeStruct(codec.Int32); packed = decoder.readUint8(); val.incognito = (packed >> 0) & 1 ? true : false; decoder.skip(1); decoder.skip(1); decoder.skip(1); val.timeout = decoder.decodeStructPointer(time$.TimeDelta); return val; }; MediaRouteProvider_CreateRoute_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouteProvider_CreateRoute_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.String, val.mediaSource); encoder.encodeStruct(codec.String, val.sinkId); encoder.encodeStruct(codec.String, val.originalPresentationId); encoder.encodeStructPointer(origin$.Origin, val.origin); encoder.encodeStruct(codec.Int32, val.tabId); packed = 0; packed |= (val.incognito & 1) << 0 encoder.writeUint8(packed); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.encodeStructPointer(time$.TimeDelta, val.timeout); }; function MediaRouteProvider_CreateRoute_ResponseParams(values) { this.initDefaults_(); this.initFields_(values); } MediaRouteProvider_CreateRoute_ResponseParams.prototype.initDefaults_ = function() { this.route = null; this.errorText = null; this.resultCode = 0; }; MediaRouteProvider_CreateRoute_ResponseParams.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouteProvider_CreateRoute_ResponseParams.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 32} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_CreateRoute_ResponseParams.route err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 0, MediaRoute, true); if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_CreateRoute_ResponseParams.errorText err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, true) if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_CreateRoute_ResponseParams.resultCode err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 16, RouteRequestResultCode); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouteProvider_CreateRoute_ResponseParams.encodedSize = codec.kStructHeaderSize + 24; MediaRouteProvider_CreateRoute_ResponseParams.decode = function(decoder) { var packed; var val = new MediaRouteProvider_CreateRoute_ResponseParams(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.route = decoder.decodeStructPointer(MediaRoute); val.errorText = decoder.decodeStruct(codec.NullableString); val.resultCode = decoder.decodeStruct(codec.Int32); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); return val; }; MediaRouteProvider_CreateRoute_ResponseParams.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouteProvider_CreateRoute_ResponseParams.encodedSize); encoder.writeUint32(0); encoder.encodeStructPointer(MediaRoute, val.route); encoder.encodeStruct(codec.NullableString, val.errorText); encoder.encodeStruct(codec.Int32, val.resultCode); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); }; function MediaRouteProvider_JoinRoute_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaRouteProvider_JoinRoute_Params.prototype.initDefaults_ = function() { this.mediaSource = null; this.presentationId = null; this.origin = null; this.tabId = 0; this.incognito = false; this.timeout = null; }; MediaRouteProvider_JoinRoute_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouteProvider_JoinRoute_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 48} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_JoinRoute_Params.mediaSource err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false) if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_JoinRoute_Params.presentationId err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false) if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_JoinRoute_Params.origin err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 16, origin$.Origin, false); if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_JoinRoute_Params.timeout err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 32, time$.TimeDelta, false); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouteProvider_JoinRoute_Params.encodedSize = codec.kStructHeaderSize + 40; MediaRouteProvider_JoinRoute_Params.decode = function(decoder) { var packed; var val = new MediaRouteProvider_JoinRoute_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.mediaSource = decoder.decodeStruct(codec.String); val.presentationId = decoder.decodeStruct(codec.String); val.origin = decoder.decodeStructPointer(origin$.Origin); val.tabId = decoder.decodeStruct(codec.Int32); packed = decoder.readUint8(); val.incognito = (packed >> 0) & 1 ? true : false; decoder.skip(1); decoder.skip(1); decoder.skip(1); val.timeout = decoder.decodeStructPointer(time$.TimeDelta); return val; }; MediaRouteProvider_JoinRoute_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouteProvider_JoinRoute_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.String, val.mediaSource); encoder.encodeStruct(codec.String, val.presentationId); encoder.encodeStructPointer(origin$.Origin, val.origin); encoder.encodeStruct(codec.Int32, val.tabId); packed = 0; packed |= (val.incognito & 1) << 0 encoder.writeUint8(packed); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.encodeStructPointer(time$.TimeDelta, val.timeout); }; function MediaRouteProvider_JoinRoute_ResponseParams(values) { this.initDefaults_(); this.initFields_(values); } MediaRouteProvider_JoinRoute_ResponseParams.prototype.initDefaults_ = function() { this.route = null; this.errorText = null; this.resultCode = 0; }; MediaRouteProvider_JoinRoute_ResponseParams.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouteProvider_JoinRoute_ResponseParams.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 32} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_JoinRoute_ResponseParams.route err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 0, MediaRoute, true); if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_JoinRoute_ResponseParams.errorText err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, true) if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_JoinRoute_ResponseParams.resultCode err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 16, RouteRequestResultCode); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouteProvider_JoinRoute_ResponseParams.encodedSize = codec.kStructHeaderSize + 24; MediaRouteProvider_JoinRoute_ResponseParams.decode = function(decoder) { var packed; var val = new MediaRouteProvider_JoinRoute_ResponseParams(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.route = decoder.decodeStructPointer(MediaRoute); val.errorText = decoder.decodeStruct(codec.NullableString); val.resultCode = decoder.decodeStruct(codec.Int32); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); return val; }; MediaRouteProvider_JoinRoute_ResponseParams.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouteProvider_JoinRoute_ResponseParams.encodedSize); encoder.writeUint32(0); encoder.encodeStructPointer(MediaRoute, val.route); encoder.encodeStruct(codec.NullableString, val.errorText); encoder.encodeStruct(codec.Int32, val.resultCode); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); }; function MediaRouteProvider_ConnectRouteByRouteId_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaRouteProvider_ConnectRouteByRouteId_Params.prototype.initDefaults_ = function() { this.mediaSource = null; this.routeId = null; this.presentationId = null; this.origin = null; this.tabId = 0; this.incognito = false; this.timeout = null; }; MediaRouteProvider_ConnectRouteByRouteId_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouteProvider_ConnectRouteByRouteId_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 56} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_ConnectRouteByRouteId_Params.mediaSource err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false) if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_ConnectRouteByRouteId_Params.routeId err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false) if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_ConnectRouteByRouteId_Params.presentationId err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 16, false) if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_ConnectRouteByRouteId_Params.origin err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 24, origin$.Origin, false); if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_ConnectRouteByRouteId_Params.timeout err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 40, time$.TimeDelta, false); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouteProvider_ConnectRouteByRouteId_Params.encodedSize = codec.kStructHeaderSize + 48; MediaRouteProvider_ConnectRouteByRouteId_Params.decode = function(decoder) { var packed; var val = new MediaRouteProvider_ConnectRouteByRouteId_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.mediaSource = decoder.decodeStruct(codec.String); val.routeId = decoder.decodeStruct(codec.String); val.presentationId = decoder.decodeStruct(codec.String); val.origin = decoder.decodeStructPointer(origin$.Origin); val.tabId = decoder.decodeStruct(codec.Int32); packed = decoder.readUint8(); val.incognito = (packed >> 0) & 1 ? true : false; decoder.skip(1); decoder.skip(1); decoder.skip(1); val.timeout = decoder.decodeStructPointer(time$.TimeDelta); return val; }; MediaRouteProvider_ConnectRouteByRouteId_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouteProvider_ConnectRouteByRouteId_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.String, val.mediaSource); encoder.encodeStruct(codec.String, val.routeId); encoder.encodeStruct(codec.String, val.presentationId); encoder.encodeStructPointer(origin$.Origin, val.origin); encoder.encodeStruct(codec.Int32, val.tabId); packed = 0; packed |= (val.incognito & 1) << 0 encoder.writeUint8(packed); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.encodeStructPointer(time$.TimeDelta, val.timeout); }; function MediaRouteProvider_ConnectRouteByRouteId_ResponseParams(values) { this.initDefaults_(); this.initFields_(values); } MediaRouteProvider_ConnectRouteByRouteId_ResponseParams.prototype.initDefaults_ = function() { this.route = null; this.errorText = null; this.resultCode = 0; }; MediaRouteProvider_ConnectRouteByRouteId_ResponseParams.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouteProvider_ConnectRouteByRouteId_ResponseParams.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 32} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_ConnectRouteByRouteId_ResponseParams.route err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 0, MediaRoute, true); if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_ConnectRouteByRouteId_ResponseParams.errorText err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, true) if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_ConnectRouteByRouteId_ResponseParams.resultCode err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 16, RouteRequestResultCode); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouteProvider_ConnectRouteByRouteId_ResponseParams.encodedSize = codec.kStructHeaderSize + 24; MediaRouteProvider_ConnectRouteByRouteId_ResponseParams.decode = function(decoder) { var packed; var val = new MediaRouteProvider_ConnectRouteByRouteId_ResponseParams(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.route = decoder.decodeStructPointer(MediaRoute); val.errorText = decoder.decodeStruct(codec.NullableString); val.resultCode = decoder.decodeStruct(codec.Int32); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); return val; }; MediaRouteProvider_ConnectRouteByRouteId_ResponseParams.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouteProvider_ConnectRouteByRouteId_ResponseParams.encodedSize); encoder.writeUint32(0); encoder.encodeStructPointer(MediaRoute, val.route); encoder.encodeStruct(codec.NullableString, val.errorText); encoder.encodeStruct(codec.Int32, val.resultCode); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); }; function MediaRouteProvider_TerminateRoute_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaRouteProvider_TerminateRoute_Params.prototype.initDefaults_ = function() { this.routeId = null; }; MediaRouteProvider_TerminateRoute_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouteProvider_TerminateRoute_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_TerminateRoute_Params.routeId err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false) if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouteProvider_TerminateRoute_Params.encodedSize = codec.kStructHeaderSize + 8; MediaRouteProvider_TerminateRoute_Params.decode = function(decoder) { var packed; var val = new MediaRouteProvider_TerminateRoute_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.routeId = decoder.decodeStruct(codec.String); return val; }; MediaRouteProvider_TerminateRoute_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouteProvider_TerminateRoute_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.String, val.routeId); }; function MediaRouteProvider_TerminateRoute_ResponseParams(values) { this.initDefaults_(); this.initFields_(values); } MediaRouteProvider_TerminateRoute_ResponseParams.prototype.initDefaults_ = function() { this.errorText = null; this.resultCode = 0; }; MediaRouteProvider_TerminateRoute_ResponseParams.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouteProvider_TerminateRoute_ResponseParams.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 24} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_TerminateRoute_ResponseParams.errorText err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, true) if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_TerminateRoute_ResponseParams.resultCode err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 8, RouteRequestResultCode); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouteProvider_TerminateRoute_ResponseParams.encodedSize = codec.kStructHeaderSize + 16; MediaRouteProvider_TerminateRoute_ResponseParams.decode = function(decoder) { var packed; var val = new MediaRouteProvider_TerminateRoute_ResponseParams(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.errorText = decoder.decodeStruct(codec.NullableString); val.resultCode = decoder.decodeStruct(codec.Int32); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); return val; }; MediaRouteProvider_TerminateRoute_ResponseParams.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouteProvider_TerminateRoute_ResponseParams.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.NullableString, val.errorText); encoder.encodeStruct(codec.Int32, val.resultCode); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); }; function MediaRouteProvider_SendRouteMessage_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaRouteProvider_SendRouteMessage_Params.prototype.initDefaults_ = function() { this.mediaRouteId = null; this.message = null; }; MediaRouteProvider_SendRouteMessage_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouteProvider_SendRouteMessage_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 24} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_SendRouteMessage_Params.mediaRouteId err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false) if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_SendRouteMessage_Params.message err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false) if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouteProvider_SendRouteMessage_Params.encodedSize = codec.kStructHeaderSize + 16; MediaRouteProvider_SendRouteMessage_Params.decode = function(decoder) { var packed; var val = new MediaRouteProvider_SendRouteMessage_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.mediaRouteId = decoder.decodeStruct(codec.String); val.message = decoder.decodeStruct(codec.String); return val; }; MediaRouteProvider_SendRouteMessage_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouteProvider_SendRouteMessage_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.String, val.mediaRouteId); encoder.encodeStruct(codec.String, val.message); }; function MediaRouteProvider_SendRouteMessage_ResponseParams(values) { this.initDefaults_(); this.initFields_(values); } MediaRouteProvider_SendRouteMessage_ResponseParams.prototype.initDefaults_ = function() { this.sent = false; }; MediaRouteProvider_SendRouteMessage_ResponseParams.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouteProvider_SendRouteMessage_ResponseParams.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouteProvider_SendRouteMessage_ResponseParams.encodedSize = codec.kStructHeaderSize + 8; MediaRouteProvider_SendRouteMessage_ResponseParams.decode = function(decoder) { var packed; var val = new MediaRouteProvider_SendRouteMessage_ResponseParams(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); packed = decoder.readUint8(); val.sent = (packed >> 0) & 1 ? true : false; decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); return val; }; MediaRouteProvider_SendRouteMessage_ResponseParams.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouteProvider_SendRouteMessage_ResponseParams.encodedSize); encoder.writeUint32(0); packed = 0; packed |= (val.sent & 1) << 0 encoder.writeUint8(packed); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); }; function MediaRouteProvider_SendRouteBinaryMessage_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaRouteProvider_SendRouteBinaryMessage_Params.prototype.initDefaults_ = function() { this.mediaRouteId = null; this.data = null; }; MediaRouteProvider_SendRouteBinaryMessage_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouteProvider_SendRouteBinaryMessage_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 24} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_SendRouteBinaryMessage_Params.mediaRouteId err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false) if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_SendRouteBinaryMessage_Params.data err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 8, 1, codec.Uint8, false, [0], 0); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouteProvider_SendRouteBinaryMessage_Params.encodedSize = codec.kStructHeaderSize + 16; MediaRouteProvider_SendRouteBinaryMessage_Params.decode = function(decoder) { var packed; var val = new MediaRouteProvider_SendRouteBinaryMessage_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.mediaRouteId = decoder.decodeStruct(codec.String); val.data = decoder.decodeArrayPointer(codec.Uint8); return val; }; MediaRouteProvider_SendRouteBinaryMessage_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouteProvider_SendRouteBinaryMessage_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.String, val.mediaRouteId); encoder.encodeArrayPointer(codec.Uint8, val.data); }; function MediaRouteProvider_SendRouteBinaryMessage_ResponseParams(values) { this.initDefaults_(); this.initFields_(values); } MediaRouteProvider_SendRouteBinaryMessage_ResponseParams.prototype.initDefaults_ = function() { this.sent = false; }; MediaRouteProvider_SendRouteBinaryMessage_ResponseParams.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouteProvider_SendRouteBinaryMessage_ResponseParams.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouteProvider_SendRouteBinaryMessage_ResponseParams.encodedSize = codec.kStructHeaderSize + 8; MediaRouteProvider_SendRouteBinaryMessage_ResponseParams.decode = function(decoder) { var packed; var val = new MediaRouteProvider_SendRouteBinaryMessage_ResponseParams(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); packed = decoder.readUint8(); val.sent = (packed >> 0) & 1 ? true : false; decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); return val; }; MediaRouteProvider_SendRouteBinaryMessage_ResponseParams.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouteProvider_SendRouteBinaryMessage_ResponseParams.encodedSize); encoder.writeUint32(0); packed = 0; packed |= (val.sent & 1) << 0 encoder.writeUint8(packed); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); }; function MediaRouteProvider_StartObservingMediaSinks_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaRouteProvider_StartObservingMediaSinks_Params.prototype.initDefaults_ = function() { this.mediaSource = null; }; MediaRouteProvider_StartObservingMediaSinks_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouteProvider_StartObservingMediaSinks_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_StartObservingMediaSinks_Params.mediaSource err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false) if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouteProvider_StartObservingMediaSinks_Params.encodedSize = codec.kStructHeaderSize + 8; MediaRouteProvider_StartObservingMediaSinks_Params.decode = function(decoder) { var packed; var val = new MediaRouteProvider_StartObservingMediaSinks_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.mediaSource = decoder.decodeStruct(codec.String); return val; }; MediaRouteProvider_StartObservingMediaSinks_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouteProvider_StartObservingMediaSinks_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.String, val.mediaSource); }; function MediaRouteProvider_StopObservingMediaSinks_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaRouteProvider_StopObservingMediaSinks_Params.prototype.initDefaults_ = function() { this.mediaSource = null; }; MediaRouteProvider_StopObservingMediaSinks_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouteProvider_StopObservingMediaSinks_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_StopObservingMediaSinks_Params.mediaSource err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false) if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouteProvider_StopObservingMediaSinks_Params.encodedSize = codec.kStructHeaderSize + 8; MediaRouteProvider_StopObservingMediaSinks_Params.decode = function(decoder) { var packed; var val = new MediaRouteProvider_StopObservingMediaSinks_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.mediaSource = decoder.decodeStruct(codec.String); return val; }; MediaRouteProvider_StopObservingMediaSinks_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouteProvider_StopObservingMediaSinks_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.String, val.mediaSource); }; function MediaRouteProvider_StartObservingMediaRoutes_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaRouteProvider_StartObservingMediaRoutes_Params.prototype.initDefaults_ = function() { this.mediaSource = null; }; MediaRouteProvider_StartObservingMediaRoutes_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouteProvider_StartObservingMediaRoutes_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_StartObservingMediaRoutes_Params.mediaSource err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false) if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouteProvider_StartObservingMediaRoutes_Params.encodedSize = codec.kStructHeaderSize + 8; MediaRouteProvider_StartObservingMediaRoutes_Params.decode = function(decoder) { var packed; var val = new MediaRouteProvider_StartObservingMediaRoutes_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.mediaSource = decoder.decodeStruct(codec.String); return val; }; MediaRouteProvider_StartObservingMediaRoutes_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouteProvider_StartObservingMediaRoutes_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.String, val.mediaSource); }; function MediaRouteProvider_StopObservingMediaRoutes_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaRouteProvider_StopObservingMediaRoutes_Params.prototype.initDefaults_ = function() { this.mediaSource = null; }; MediaRouteProvider_StopObservingMediaRoutes_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouteProvider_StopObservingMediaRoutes_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_StopObservingMediaRoutes_Params.mediaSource err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false) if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouteProvider_StopObservingMediaRoutes_Params.encodedSize = codec.kStructHeaderSize + 8; MediaRouteProvider_StopObservingMediaRoutes_Params.decode = function(decoder) { var packed; var val = new MediaRouteProvider_StopObservingMediaRoutes_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.mediaSource = decoder.decodeStruct(codec.String); return val; }; MediaRouteProvider_StopObservingMediaRoutes_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouteProvider_StopObservingMediaRoutes_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.String, val.mediaSource); }; function MediaRouteProvider_StartListeningForRouteMessages_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaRouteProvider_StartListeningForRouteMessages_Params.prototype.initDefaults_ = function() { this.routeId = null; }; MediaRouteProvider_StartListeningForRouteMessages_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouteProvider_StartListeningForRouteMessages_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_StartListeningForRouteMessages_Params.routeId err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false) if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouteProvider_StartListeningForRouteMessages_Params.encodedSize = codec.kStructHeaderSize + 8; MediaRouteProvider_StartListeningForRouteMessages_Params.decode = function(decoder) { var packed; var val = new MediaRouteProvider_StartListeningForRouteMessages_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.routeId = decoder.decodeStruct(codec.String); return val; }; MediaRouteProvider_StartListeningForRouteMessages_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouteProvider_StartListeningForRouteMessages_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.String, val.routeId); }; function MediaRouteProvider_StopListeningForRouteMessages_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaRouteProvider_StopListeningForRouteMessages_Params.prototype.initDefaults_ = function() { this.routeId = null; }; MediaRouteProvider_StopListeningForRouteMessages_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouteProvider_StopListeningForRouteMessages_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_StopListeningForRouteMessages_Params.routeId err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false) if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouteProvider_StopListeningForRouteMessages_Params.encodedSize = codec.kStructHeaderSize + 8; MediaRouteProvider_StopListeningForRouteMessages_Params.decode = function(decoder) { var packed; var val = new MediaRouteProvider_StopListeningForRouteMessages_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.routeId = decoder.decodeStruct(codec.String); return val; }; MediaRouteProvider_StopListeningForRouteMessages_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouteProvider_StopListeningForRouteMessages_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.String, val.routeId); }; function MediaRouteProvider_DetachRoute_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaRouteProvider_DetachRoute_Params.prototype.initDefaults_ = function() { this.routeId = null; }; MediaRouteProvider_DetachRoute_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouteProvider_DetachRoute_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_DetachRoute_Params.routeId err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false) if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouteProvider_DetachRoute_Params.encodedSize = codec.kStructHeaderSize + 8; MediaRouteProvider_DetachRoute_Params.decode = function(decoder) { var packed; var val = new MediaRouteProvider_DetachRoute_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.routeId = decoder.decodeStruct(codec.String); return val; }; MediaRouteProvider_DetachRoute_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouteProvider_DetachRoute_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.String, val.routeId); }; function MediaRouteProvider_EnableMdnsDiscovery_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaRouteProvider_EnableMdnsDiscovery_Params.prototype.initDefaults_ = function() { }; MediaRouteProvider_EnableMdnsDiscovery_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouteProvider_EnableMdnsDiscovery_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 8} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouteProvider_EnableMdnsDiscovery_Params.encodedSize = codec.kStructHeaderSize + 0; MediaRouteProvider_EnableMdnsDiscovery_Params.decode = function(decoder) { var packed; var val = new MediaRouteProvider_EnableMdnsDiscovery_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); return val; }; MediaRouteProvider_EnableMdnsDiscovery_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouteProvider_EnableMdnsDiscovery_Params.encodedSize); encoder.writeUint32(0); }; function MediaRouteProvider_UpdateMediaSinks_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaRouteProvider_UpdateMediaSinks_Params.prototype.initDefaults_ = function() { this.mediaSource = null; }; MediaRouteProvider_UpdateMediaSinks_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouteProvider_UpdateMediaSinks_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_UpdateMediaSinks_Params.mediaSource err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false) if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouteProvider_UpdateMediaSinks_Params.encodedSize = codec.kStructHeaderSize + 8; MediaRouteProvider_UpdateMediaSinks_Params.decode = function(decoder) { var packed; var val = new MediaRouteProvider_UpdateMediaSinks_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.mediaSource = decoder.decodeStruct(codec.String); return val; }; MediaRouteProvider_UpdateMediaSinks_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouteProvider_UpdateMediaSinks_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.String, val.mediaSource); }; function MediaRouteProvider_SearchSinks_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaRouteProvider_SearchSinks_Params.prototype.initDefaults_ = function() { this.sinkId = null; this.mediaSource = null; this.searchCriteria = null; }; MediaRouteProvider_SearchSinks_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouteProvider_SearchSinks_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 32} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_SearchSinks_Params.sinkId err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false) if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_SearchSinks_Params.mediaSource err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false) if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_SearchSinks_Params.searchCriteria err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 16, SinkSearchCriteria, false); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouteProvider_SearchSinks_Params.encodedSize = codec.kStructHeaderSize + 24; MediaRouteProvider_SearchSinks_Params.decode = function(decoder) { var packed; var val = new MediaRouteProvider_SearchSinks_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.sinkId = decoder.decodeStruct(codec.String); val.mediaSource = decoder.decodeStruct(codec.String); val.searchCriteria = decoder.decodeStructPointer(SinkSearchCriteria); return val; }; MediaRouteProvider_SearchSinks_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouteProvider_SearchSinks_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.String, val.sinkId); encoder.encodeStruct(codec.String, val.mediaSource); encoder.encodeStructPointer(SinkSearchCriteria, val.searchCriteria); }; function MediaRouteProvider_SearchSinks_ResponseParams(values) { this.initDefaults_(); this.initFields_(values); } MediaRouteProvider_SearchSinks_ResponseParams.prototype.initDefaults_ = function() { this.sinkId = null; }; MediaRouteProvider_SearchSinks_ResponseParams.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouteProvider_SearchSinks_ResponseParams.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_SearchSinks_ResponseParams.sinkId err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false) if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouteProvider_SearchSinks_ResponseParams.encodedSize = codec.kStructHeaderSize + 8; MediaRouteProvider_SearchSinks_ResponseParams.decode = function(decoder) { var packed; var val = new MediaRouteProvider_SearchSinks_ResponseParams(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.sinkId = decoder.decodeStruct(codec.String); return val; }; MediaRouteProvider_SearchSinks_ResponseParams.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouteProvider_SearchSinks_ResponseParams.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.String, val.sinkId); }; function MediaRouteProvider_ProvideSinks_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaRouteProvider_ProvideSinks_Params.prototype.initDefaults_ = function() { this.providerName = null; this.sinks = null; }; MediaRouteProvider_ProvideSinks_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouteProvider_ProvideSinks_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 24} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_ProvideSinks_Params.providerName err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false) if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_ProvideSinks_Params.sinks err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 8, 8, new codec.PointerTo(MediaSink), false, [0], 0); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouteProvider_ProvideSinks_Params.encodedSize = codec.kStructHeaderSize + 16; MediaRouteProvider_ProvideSinks_Params.decode = function(decoder) { var packed; var val = new MediaRouteProvider_ProvideSinks_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.providerName = decoder.decodeStruct(codec.String); val.sinks = decoder.decodeArrayPointer(new codec.PointerTo(MediaSink)); return val; }; MediaRouteProvider_ProvideSinks_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouteProvider_ProvideSinks_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.String, val.providerName); encoder.encodeArrayPointer(new codec.PointerTo(MediaSink), val.sinks); }; function MediaRouteProvider_CreateMediaRouteController_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaRouteProvider_CreateMediaRouteController_Params.prototype.initDefaults_ = function() { this.routeId = null; this.mediaController = new bindings.InterfaceRequest(); this.observer = new media_status$.MediaStatusObserverPtr(); }; MediaRouteProvider_CreateMediaRouteController_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouteProvider_CreateMediaRouteController_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 32} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_CreateMediaRouteController_Params.routeId err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false) if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_CreateMediaRouteController_Params.mediaController err = messageValidator.validateInterfaceRequest(offset + codec.kStructHeaderSize + 8, false) if (err !== validator.validationError.NONE) return err; // validate MediaRouteProvider_CreateMediaRouteController_Params.observer err = messageValidator.validateInterface(offset + codec.kStructHeaderSize + 12, false); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouteProvider_CreateMediaRouteController_Params.encodedSize = codec.kStructHeaderSize + 24; MediaRouteProvider_CreateMediaRouteController_Params.decode = function(decoder) { var packed; var val = new MediaRouteProvider_CreateMediaRouteController_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.routeId = decoder.decodeStruct(codec.String); val.mediaController = decoder.decodeStruct(codec.InterfaceRequest); val.observer = decoder.decodeStruct(new codec.Interface(media_status$.MediaStatusObserverPtr)); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); return val; }; MediaRouteProvider_CreateMediaRouteController_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouteProvider_CreateMediaRouteController_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.String, val.routeId); encoder.encodeStruct(codec.InterfaceRequest, val.mediaController); encoder.encodeStruct(new codec.Interface(media_status$.MediaStatusObserverPtr), val.observer); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); }; function MediaRouteProvider_CreateMediaRouteController_ResponseParams(values) { this.initDefaults_(); this.initFields_(values); } MediaRouteProvider_CreateMediaRouteController_ResponseParams.prototype.initDefaults_ = function() { this.success = false; }; MediaRouteProvider_CreateMediaRouteController_ResponseParams.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouteProvider_CreateMediaRouteController_ResponseParams.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouteProvider_CreateMediaRouteController_ResponseParams.encodedSize = codec.kStructHeaderSize + 8; MediaRouteProvider_CreateMediaRouteController_ResponseParams.decode = function(decoder) { var packed; var val = new MediaRouteProvider_CreateMediaRouteController_ResponseParams(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); packed = decoder.readUint8(); val.success = (packed >> 0) & 1 ? true : false; decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); return val; }; MediaRouteProvider_CreateMediaRouteController_ResponseParams.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouteProvider_CreateMediaRouteController_ResponseParams.encodedSize); encoder.writeUint32(0); packed = 0; packed |= (val.success & 1) << 0 encoder.writeUint8(packed); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); }; function MediaRouter_RegisterMediaRouteProvider_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaRouter_RegisterMediaRouteProvider_Params.prototype.initDefaults_ = function() { this.providerId = 0; this.mediaRouterProvider = new MediaRouteProviderPtr(); }; MediaRouter_RegisterMediaRouteProvider_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouter_RegisterMediaRouteProvider_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 24} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRouter_RegisterMediaRouteProvider_Params.providerId err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 0, MediaRouteProvider.Id); if (err !== validator.validationError.NONE) return err; // validate MediaRouter_RegisterMediaRouteProvider_Params.mediaRouterProvider err = messageValidator.validateInterface(offset + codec.kStructHeaderSize + 4, false); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouter_RegisterMediaRouteProvider_Params.encodedSize = codec.kStructHeaderSize + 16; MediaRouter_RegisterMediaRouteProvider_Params.decode = function(decoder) { var packed; var val = new MediaRouter_RegisterMediaRouteProvider_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.providerId = decoder.decodeStruct(codec.Int32); val.mediaRouterProvider = decoder.decodeStruct(new codec.Interface(MediaRouteProviderPtr)); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); return val; }; MediaRouter_RegisterMediaRouteProvider_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouter_RegisterMediaRouteProvider_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.Int32, val.providerId); encoder.encodeStruct(new codec.Interface(MediaRouteProviderPtr), val.mediaRouterProvider); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); }; function MediaRouter_RegisterMediaRouteProvider_ResponseParams(values) { this.initDefaults_(); this.initFields_(values); } MediaRouter_RegisterMediaRouteProvider_ResponseParams.prototype.initDefaults_ = function() { this.instanceId = null; this.config = null; }; MediaRouter_RegisterMediaRouteProvider_ResponseParams.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouter_RegisterMediaRouteProvider_ResponseParams.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 24} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRouter_RegisterMediaRouteProvider_ResponseParams.instanceId err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false) if (err !== validator.validationError.NONE) return err; // validate MediaRouter_RegisterMediaRouteProvider_ResponseParams.config err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 8, MediaRouteProviderConfig, false); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouter_RegisterMediaRouteProvider_ResponseParams.encodedSize = codec.kStructHeaderSize + 16; MediaRouter_RegisterMediaRouteProvider_ResponseParams.decode = function(decoder) { var packed; var val = new MediaRouter_RegisterMediaRouteProvider_ResponseParams(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.instanceId = decoder.decodeStruct(codec.String); val.config = decoder.decodeStructPointer(MediaRouteProviderConfig); return val; }; MediaRouter_RegisterMediaRouteProvider_ResponseParams.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouter_RegisterMediaRouteProvider_ResponseParams.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.String, val.instanceId); encoder.encodeStructPointer(MediaRouteProviderConfig, val.config); }; function MediaRouter_OnSinksReceived_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaRouter_OnSinksReceived_Params.prototype.initDefaults_ = function() { this.providerId = 0; this.mediaSource = null; this.sinks = null; this.origins = null; }; MediaRouter_OnSinksReceived_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouter_OnSinksReceived_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 40} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRouter_OnSinksReceived_Params.providerId err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 0, MediaRouteProvider.Id); if (err !== validator.validationError.NONE) return err; // validate MediaRouter_OnSinksReceived_Params.mediaSource err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false) if (err !== validator.validationError.NONE) return err; // validate MediaRouter_OnSinksReceived_Params.sinks err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 16, 8, new codec.PointerTo(MediaSink), false, [0], 0); if (err !== validator.validationError.NONE) return err; // validate MediaRouter_OnSinksReceived_Params.origins err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 24, 8, new codec.PointerTo(origin$.Origin), false, [0], 0); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouter_OnSinksReceived_Params.encodedSize = codec.kStructHeaderSize + 32; MediaRouter_OnSinksReceived_Params.decode = function(decoder) { var packed; var val = new MediaRouter_OnSinksReceived_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.providerId = decoder.decodeStruct(codec.Int32); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); val.mediaSource = decoder.decodeStruct(codec.String); val.sinks = decoder.decodeArrayPointer(new codec.PointerTo(MediaSink)); val.origins = decoder.decodeArrayPointer(new codec.PointerTo(origin$.Origin)); return val; }; MediaRouter_OnSinksReceived_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouter_OnSinksReceived_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.Int32, val.providerId); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.encodeStruct(codec.String, val.mediaSource); encoder.encodeArrayPointer(new codec.PointerTo(MediaSink), val.sinks); encoder.encodeArrayPointer(new codec.PointerTo(origin$.Origin), val.origins); }; function MediaRouter_OnIssue_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaRouter_OnIssue_Params.prototype.initDefaults_ = function() { this.issue = null; }; MediaRouter_OnIssue_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouter_OnIssue_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRouter_OnIssue_Params.issue err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 0, Issue, false); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouter_OnIssue_Params.encodedSize = codec.kStructHeaderSize + 8; MediaRouter_OnIssue_Params.decode = function(decoder) { var packed; var val = new MediaRouter_OnIssue_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.issue = decoder.decodeStructPointer(Issue); return val; }; MediaRouter_OnIssue_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouter_OnIssue_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStructPointer(Issue, val.issue); }; function MediaRouter_OnRoutesUpdated_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaRouter_OnRoutesUpdated_Params.prototype.initDefaults_ = function() { this.providerId = 0; this.routes = null; this.mediaSource = null; this.joinableRouteIds = null; }; MediaRouter_OnRoutesUpdated_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouter_OnRoutesUpdated_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 40} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRouter_OnRoutesUpdated_Params.providerId err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 0, MediaRouteProvider.Id); if (err !== validator.validationError.NONE) return err; // validate MediaRouter_OnRoutesUpdated_Params.routes err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 8, 8, new codec.PointerTo(MediaRoute), false, [0], 0); if (err !== validator.validationError.NONE) return err; // validate MediaRouter_OnRoutesUpdated_Params.mediaSource err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 16, false) if (err !== validator.validationError.NONE) return err; // validate MediaRouter_OnRoutesUpdated_Params.joinableRouteIds err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 24, 8, codec.String, false, [0, 0], 0); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouter_OnRoutesUpdated_Params.encodedSize = codec.kStructHeaderSize + 32; MediaRouter_OnRoutesUpdated_Params.decode = function(decoder) { var packed; var val = new MediaRouter_OnRoutesUpdated_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.providerId = decoder.decodeStruct(codec.Int32); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); val.routes = decoder.decodeArrayPointer(new codec.PointerTo(MediaRoute)); val.mediaSource = decoder.decodeStruct(codec.String); val.joinableRouteIds = decoder.decodeArrayPointer(codec.String); return val; }; MediaRouter_OnRoutesUpdated_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouter_OnRoutesUpdated_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.Int32, val.providerId); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.encodeArrayPointer(new codec.PointerTo(MediaRoute), val.routes); encoder.encodeStruct(codec.String, val.mediaSource); encoder.encodeArrayPointer(codec.String, val.joinableRouteIds); }; function MediaRouter_OnSinkAvailabilityUpdated_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaRouter_OnSinkAvailabilityUpdated_Params.prototype.initDefaults_ = function() { this.providerId = 0; this.availability = 0; }; MediaRouter_OnSinkAvailabilityUpdated_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouter_OnSinkAvailabilityUpdated_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRouter_OnSinkAvailabilityUpdated_Params.providerId err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 0, MediaRouteProvider.Id); if (err !== validator.validationError.NONE) return err; // validate MediaRouter_OnSinkAvailabilityUpdated_Params.availability err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 4, MediaRouter.SinkAvailability); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouter_OnSinkAvailabilityUpdated_Params.encodedSize = codec.kStructHeaderSize + 8; MediaRouter_OnSinkAvailabilityUpdated_Params.decode = function(decoder) { var packed; var val = new MediaRouter_OnSinkAvailabilityUpdated_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.providerId = decoder.decodeStruct(codec.Int32); val.availability = decoder.decodeStruct(codec.Int32); return val; }; MediaRouter_OnSinkAvailabilityUpdated_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouter_OnSinkAvailabilityUpdated_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.Int32, val.providerId); encoder.encodeStruct(codec.Int32, val.availability); }; function MediaRouter_OnPresentationConnectionStateChanged_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaRouter_OnPresentationConnectionStateChanged_Params.prototype.initDefaults_ = function() { this.routeId = null; this.state = 0; }; MediaRouter_OnPresentationConnectionStateChanged_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouter_OnPresentationConnectionStateChanged_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 24} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRouter_OnPresentationConnectionStateChanged_Params.routeId err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false) if (err !== validator.validationError.NONE) return err; // validate MediaRouter_OnPresentationConnectionStateChanged_Params.state err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 8, MediaRouter.PresentationConnectionState); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouter_OnPresentationConnectionStateChanged_Params.encodedSize = codec.kStructHeaderSize + 16; MediaRouter_OnPresentationConnectionStateChanged_Params.decode = function(decoder) { var packed; var val = new MediaRouter_OnPresentationConnectionStateChanged_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.routeId = decoder.decodeStruct(codec.String); val.state = decoder.decodeStruct(codec.Int32); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); return val; }; MediaRouter_OnPresentationConnectionStateChanged_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouter_OnPresentationConnectionStateChanged_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.String, val.routeId); encoder.encodeStruct(codec.Int32, val.state); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); }; function MediaRouter_OnPresentationConnectionClosed_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaRouter_OnPresentationConnectionClosed_Params.prototype.initDefaults_ = function() { this.routeId = null; this.reason = 0; this.message = null; }; MediaRouter_OnPresentationConnectionClosed_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouter_OnPresentationConnectionClosed_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 32} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRouter_OnPresentationConnectionClosed_Params.routeId err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false) if (err !== validator.validationError.NONE) return err; // validate MediaRouter_OnPresentationConnectionClosed_Params.reason err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 8, MediaRouter.PresentationConnectionCloseReason); if (err !== validator.validationError.NONE) return err; // validate MediaRouter_OnPresentationConnectionClosed_Params.message err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 16, false) if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouter_OnPresentationConnectionClosed_Params.encodedSize = codec.kStructHeaderSize + 24; MediaRouter_OnPresentationConnectionClosed_Params.decode = function(decoder) { var packed; var val = new MediaRouter_OnPresentationConnectionClosed_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.routeId = decoder.decodeStruct(codec.String); val.reason = decoder.decodeStruct(codec.Int32); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); val.message = decoder.decodeStruct(codec.String); return val; }; MediaRouter_OnPresentationConnectionClosed_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouter_OnPresentationConnectionClosed_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.String, val.routeId); encoder.encodeStruct(codec.Int32, val.reason); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.encodeStruct(codec.String, val.message); }; function MediaRouter_OnRouteMessagesReceived_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaRouter_OnRouteMessagesReceived_Params.prototype.initDefaults_ = function() { this.routeId = null; this.messages = null; }; MediaRouter_OnRouteMessagesReceived_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouter_OnRouteMessagesReceived_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 24} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRouter_OnRouteMessagesReceived_Params.routeId err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false) if (err !== validator.validationError.NONE) return err; // validate MediaRouter_OnRouteMessagesReceived_Params.messages err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 8, 8, new codec.PointerTo(RouteMessage), false, [0], 0); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouter_OnRouteMessagesReceived_Params.encodedSize = codec.kStructHeaderSize + 16; MediaRouter_OnRouteMessagesReceived_Params.decode = function(decoder) { var packed; var val = new MediaRouter_OnRouteMessagesReceived_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.routeId = decoder.decodeStruct(codec.String); val.messages = decoder.decodeArrayPointer(new codec.PointerTo(RouteMessage)); return val; }; MediaRouter_OnRouteMessagesReceived_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouter_OnRouteMessagesReceived_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.String, val.routeId); encoder.encodeArrayPointer(new codec.PointerTo(RouteMessage), val.messages); }; function MediaRouter_OnMediaRemoterCreated_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaRouter_OnMediaRemoterCreated_Params.prototype.initDefaults_ = function() { this.tabId = 0; this.remoter = new mirror_service_remoting$.MirrorServiceRemoterPtr(); this.remotingSource = new bindings.InterfaceRequest(); }; MediaRouter_OnMediaRemoterCreated_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaRouter_OnMediaRemoterCreated_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 24} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaRouter_OnMediaRemoterCreated_Params.remoter err = messageValidator.validateInterface(offset + codec.kStructHeaderSize + 4, false); if (err !== validator.validationError.NONE) return err; // validate MediaRouter_OnMediaRemoterCreated_Params.remotingSource err = messageValidator.validateInterfaceRequest(offset + codec.kStructHeaderSize + 12, false) if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaRouter_OnMediaRemoterCreated_Params.encodedSize = codec.kStructHeaderSize + 16; MediaRouter_OnMediaRemoterCreated_Params.decode = function(decoder) { var packed; var val = new MediaRouter_OnMediaRemoterCreated_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.tabId = decoder.decodeStruct(codec.Int32); val.remoter = decoder.decodeStruct(new codec.Interface(mirror_service_remoting$.MirrorServiceRemoterPtr)); val.remotingSource = decoder.decodeStruct(codec.InterfaceRequest); return val; }; MediaRouter_OnMediaRemoterCreated_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaRouter_OnMediaRemoterCreated_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.Int32, val.tabId); encoder.encodeStruct(new codec.Interface(mirror_service_remoting$.MirrorServiceRemoterPtr), val.remoter); encoder.encodeStruct(codec.InterfaceRequest, val.remotingSource); }; function MediaSinkExtraData(value) { this.initDefault_(); this.initValue_(value); } MediaSinkExtraData.Tags = { dialMediaSink: 0, castMediaSink: 1, }; MediaSinkExtraData.prototype.initDefault_ = function() { this.$data = null; this.$tag = undefined; } MediaSinkExtraData.prototype.initValue_ = function(value) { if (value == undefined) { return; } var keys = Object.keys(value); if (keys.length == 0) { return; } if (keys.length > 1) { throw new TypeError("You may set only one member on a union."); } var fields = [ "dialMediaSink", "castMediaSink", ]; if (fields.indexOf(keys[0]) < 0) { throw new ReferenceError(keys[0] + " is not a MediaSinkExtraData member."); } this[keys[0]] = value[keys[0]]; } Object.defineProperty(MediaSinkExtraData.prototype, "dialMediaSink", { get: function() { if (this.$tag != MediaSinkExtraData.Tags.dialMediaSink) { throw new ReferenceError( "MediaSinkExtraData.dialMediaSink is not currently set."); } return this.$data; }, set: function(value) { this.$tag = MediaSinkExtraData.Tags.dialMediaSink; this.$data = value; } }); Object.defineProperty(MediaSinkExtraData.prototype, "castMediaSink", { get: function() { if (this.$tag != MediaSinkExtraData.Tags.castMediaSink) { throw new ReferenceError( "MediaSinkExtraData.castMediaSink is not currently set."); } return this.$data; }, set: function(value) { this.$tag = MediaSinkExtraData.Tags.castMediaSink; this.$data = value; } }); MediaSinkExtraData.encode = function(encoder, val) { if (val == null) { encoder.writeUint64(0); encoder.writeUint64(0); return; } if (val.$tag == undefined) { throw new TypeError("Cannot encode unions with an unknown member set."); } encoder.writeUint32(16); encoder.writeUint32(val.$tag); switch (val.$tag) { case MediaSinkExtraData.Tags.dialMediaSink: encoder.encodeStructPointer(DialMediaSink, val.dialMediaSink); break; case MediaSinkExtraData.Tags.castMediaSink: encoder.encodeStructPointer(CastMediaSink, val.castMediaSink); break; } encoder.align(); }; MediaSinkExtraData.decode = function(decoder) { var size = decoder.readUint32(); if (size == 0) { decoder.readUint32(); decoder.readUint64(); return null; } var result = new MediaSinkExtraData(); var tag = decoder.readUint32(); switch (tag) { case MediaSinkExtraData.Tags.dialMediaSink: result.dialMediaSink = decoder.decodeStructPointer(DialMediaSink); break; case MediaSinkExtraData.Tags.castMediaSink: result.castMediaSink = decoder.decodeStructPointer(CastMediaSink); break; } decoder.align(); return result; }; MediaSinkExtraData.validate = function(messageValidator, offset) { var size = messageValidator.decodeUnionSize(offset); if (size != 16) { return validator.validationError.INVALID_UNION_SIZE; } var tag = messageValidator.decodeUnionTag(offset); var data_offset = offset + 8; var err; switch (tag) { case MediaSinkExtraData.Tags.dialMediaSink: // validate MediaSinkExtraData.dialMediaSink err = messageValidator.validateStructPointer(data_offset, DialMediaSink, false); if (err !== validator.validationError.NONE) return err; break; case MediaSinkExtraData.Tags.castMediaSink: // validate MediaSinkExtraData.castMediaSink err = messageValidator.validateStructPointer(data_offset, CastMediaSink, false); if (err !== validator.validationError.NONE) return err; break; } return validator.validationError.NONE; }; MediaSinkExtraData.encodedSize = 16; var kMediaRouteProvider_CreateRoute_Name = 2021030730; var kMediaRouteProvider_JoinRoute_Name = 1454041253; var kMediaRouteProvider_ConnectRouteByRouteId_Name = 738462639; var kMediaRouteProvider_TerminateRoute_Name = 55651359; var kMediaRouteProvider_SendRouteMessage_Name = 137843099; var kMediaRouteProvider_SendRouteBinaryMessage_Name = 162571134; var kMediaRouteProvider_StartObservingMediaSinks_Name = 1300861070; var kMediaRouteProvider_StopObservingMediaSinks_Name = 995635284; var kMediaRouteProvider_StartObservingMediaRoutes_Name = 867741207; var kMediaRouteProvider_StopObservingMediaRoutes_Name = 141846925; var kMediaRouteProvider_StartListeningForRouteMessages_Name = 1278472312; var kMediaRouteProvider_StopListeningForRouteMessages_Name = 1473668240; var kMediaRouteProvider_DetachRoute_Name = 1051108802; var kMediaRouteProvider_EnableMdnsDiscovery_Name = 1822352056; var kMediaRouteProvider_UpdateMediaSinks_Name = 1961935818; var kMediaRouteProvider_SearchSinks_Name = 984423445; var kMediaRouteProvider_ProvideSinks_Name = 1314766317; var kMediaRouteProvider_CreateMediaRouteController_Name = 900573253; function MediaRouteProviderPtr(handleOrPtrInfo) { this.ptr = new bindings.InterfacePtrController(MediaRouteProvider, handleOrPtrInfo); } function MediaRouteProviderAssociatedPtr(associatedInterfacePtrInfo) { this.ptr = new associatedBindings.AssociatedInterfacePtrController( MediaRouteProvider, associatedInterfacePtrInfo); } MediaRouteProviderAssociatedPtr.prototype = Object.create(MediaRouteProviderPtr.prototype); MediaRouteProviderAssociatedPtr.prototype.constructor = MediaRouteProviderAssociatedPtr; function MediaRouteProviderProxy(receiver) { this.receiver_ = receiver; } MediaRouteProviderPtr.prototype.createRoute = function() { return MediaRouteProviderProxy.prototype.createRoute .apply(this.ptr.getProxy(), arguments); }; MediaRouteProviderProxy.prototype.createRoute = function(mediaSource, sinkId, originalPresentationId, origin, tabId, timeout, incognito) { var params = new MediaRouteProvider_CreateRoute_Params(); params.mediaSource = mediaSource; params.sinkId = sinkId; params.originalPresentationId = originalPresentationId; params.origin = origin; params.tabId = tabId; params.timeout = timeout; params.incognito = incognito; return new Promise(function(resolve, reject) { var builder = new codec.MessageV1Builder( kMediaRouteProvider_CreateRoute_Name, codec.align(MediaRouteProvider_CreateRoute_Params.encodedSize), codec.kMessageExpectsResponse, 0); builder.encodeStruct(MediaRouteProvider_CreateRoute_Params, params); var message = builder.finish(); this.receiver_.acceptAndExpectResponse(message).then(function(message) { var reader = new codec.MessageReader(message); var responseParams = reader.decodeStruct(MediaRouteProvider_CreateRoute_ResponseParams); resolve(responseParams); }).catch(function(result) { reject(Error("Connection error: " + result)); }); }.bind(this)); }; MediaRouteProviderPtr.prototype.joinRoute = function() { return MediaRouteProviderProxy.prototype.joinRoute .apply(this.ptr.getProxy(), arguments); }; MediaRouteProviderProxy.prototype.joinRoute = function(mediaSource, presentationId, origin, tabId, timeout, incognito) { var params = new MediaRouteProvider_JoinRoute_Params(); params.mediaSource = mediaSource; params.presentationId = presentationId; params.origin = origin; params.tabId = tabId; params.timeout = timeout; params.incognito = incognito; return new Promise(function(resolve, reject) { var builder = new codec.MessageV1Builder( kMediaRouteProvider_JoinRoute_Name, codec.align(MediaRouteProvider_JoinRoute_Params.encodedSize), codec.kMessageExpectsResponse, 0); builder.encodeStruct(MediaRouteProvider_JoinRoute_Params, params); var message = builder.finish(); this.receiver_.acceptAndExpectResponse(message).then(function(message) { var reader = new codec.MessageReader(message); var responseParams = reader.decodeStruct(MediaRouteProvider_JoinRoute_ResponseParams); resolve(responseParams); }).catch(function(result) { reject(Error("Connection error: " + result)); }); }.bind(this)); }; MediaRouteProviderPtr.prototype.connectRouteByRouteId = function() { return MediaRouteProviderProxy.prototype.connectRouteByRouteId .apply(this.ptr.getProxy(), arguments); }; MediaRouteProviderProxy.prototype.connectRouteByRouteId = function(mediaSource, routeId, presentationId, origin, tabId, timeout, incognito) { var params = new MediaRouteProvider_ConnectRouteByRouteId_Params(); params.mediaSource = mediaSource; params.routeId = routeId; params.presentationId = presentationId; params.origin = origin; params.tabId = tabId; params.timeout = timeout; params.incognito = incognito; return new Promise(function(resolve, reject) { var builder = new codec.MessageV1Builder( kMediaRouteProvider_ConnectRouteByRouteId_Name, codec.align(MediaRouteProvider_ConnectRouteByRouteId_Params.encodedSize), codec.kMessageExpectsResponse, 0); builder.encodeStruct(MediaRouteProvider_ConnectRouteByRouteId_Params, params); var message = builder.finish(); this.receiver_.acceptAndExpectResponse(message).then(function(message) { var reader = new codec.MessageReader(message); var responseParams = reader.decodeStruct(MediaRouteProvider_ConnectRouteByRouteId_ResponseParams); resolve(responseParams); }).catch(function(result) { reject(Error("Connection error: " + result)); }); }.bind(this)); }; MediaRouteProviderPtr.prototype.terminateRoute = function() { return MediaRouteProviderProxy.prototype.terminateRoute .apply(this.ptr.getProxy(), arguments); }; MediaRouteProviderProxy.prototype.terminateRoute = function(routeId) { var params = new MediaRouteProvider_TerminateRoute_Params(); params.routeId = routeId; return new Promise(function(resolve, reject) { var builder = new codec.MessageV1Builder( kMediaRouteProvider_TerminateRoute_Name, codec.align(MediaRouteProvider_TerminateRoute_Params.encodedSize), codec.kMessageExpectsResponse, 0); builder.encodeStruct(MediaRouteProvider_TerminateRoute_Params, params); var message = builder.finish(); this.receiver_.acceptAndExpectResponse(message).then(function(message) { var reader = new codec.MessageReader(message); var responseParams = reader.decodeStruct(MediaRouteProvider_TerminateRoute_ResponseParams); resolve(responseParams); }).catch(function(result) { reject(Error("Connection error: " + result)); }); }.bind(this)); }; MediaRouteProviderPtr.prototype.sendRouteMessage = function() { return MediaRouteProviderProxy.prototype.sendRouteMessage .apply(this.ptr.getProxy(), arguments); }; MediaRouteProviderProxy.prototype.sendRouteMessage = function(mediaRouteId, message) { var params = new MediaRouteProvider_SendRouteMessage_Params(); params.mediaRouteId = mediaRouteId; params.message = message; return new Promise(function(resolve, reject) { var builder = new codec.MessageV1Builder( kMediaRouteProvider_SendRouteMessage_Name, codec.align(MediaRouteProvider_SendRouteMessage_Params.encodedSize), codec.kMessageExpectsResponse, 0); builder.encodeStruct(MediaRouteProvider_SendRouteMessage_Params, params); var message = builder.finish(); this.receiver_.acceptAndExpectResponse(message).then(function(message) { var reader = new codec.MessageReader(message); var responseParams = reader.decodeStruct(MediaRouteProvider_SendRouteMessage_ResponseParams); resolve(responseParams); }).catch(function(result) { reject(Error("Connection error: " + result)); }); }.bind(this)); }; MediaRouteProviderPtr.prototype.sendRouteBinaryMessage = function() { return MediaRouteProviderProxy.prototype.sendRouteBinaryMessage .apply(this.ptr.getProxy(), arguments); }; MediaRouteProviderProxy.prototype.sendRouteBinaryMessage = function(mediaRouteId, data) { var params = new MediaRouteProvider_SendRouteBinaryMessage_Params(); params.mediaRouteId = mediaRouteId; params.data = data; return new Promise(function(resolve, reject) { var builder = new codec.MessageV1Builder( kMediaRouteProvider_SendRouteBinaryMessage_Name, codec.align(MediaRouteProvider_SendRouteBinaryMessage_Params.encodedSize), codec.kMessageExpectsResponse, 0); builder.encodeStruct(MediaRouteProvider_SendRouteBinaryMessage_Params, params); var message = builder.finish(); this.receiver_.acceptAndExpectResponse(message).then(function(message) { var reader = new codec.MessageReader(message); var responseParams = reader.decodeStruct(MediaRouteProvider_SendRouteBinaryMessage_ResponseParams); resolve(responseParams); }).catch(function(result) { reject(Error("Connection error: " + result)); }); }.bind(this)); }; MediaRouteProviderPtr.prototype.startObservingMediaSinks = function() { return MediaRouteProviderProxy.prototype.startObservingMediaSinks .apply(this.ptr.getProxy(), arguments); }; MediaRouteProviderProxy.prototype.startObservingMediaSinks = function(mediaSource) { var params = new MediaRouteProvider_StartObservingMediaSinks_Params(); params.mediaSource = mediaSource; var builder = new codec.MessageV0Builder( kMediaRouteProvider_StartObservingMediaSinks_Name, codec.align(MediaRouteProvider_StartObservingMediaSinks_Params.encodedSize)); builder.encodeStruct(MediaRouteProvider_StartObservingMediaSinks_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; MediaRouteProviderPtr.prototype.stopObservingMediaSinks = function() { return MediaRouteProviderProxy.prototype.stopObservingMediaSinks .apply(this.ptr.getProxy(), arguments); }; MediaRouteProviderProxy.prototype.stopObservingMediaSinks = function(mediaSource) { var params = new MediaRouteProvider_StopObservingMediaSinks_Params(); params.mediaSource = mediaSource; var builder = new codec.MessageV0Builder( kMediaRouteProvider_StopObservingMediaSinks_Name, codec.align(MediaRouteProvider_StopObservingMediaSinks_Params.encodedSize)); builder.encodeStruct(MediaRouteProvider_StopObservingMediaSinks_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; MediaRouteProviderPtr.prototype.startObservingMediaRoutes = function() { return MediaRouteProviderProxy.prototype.startObservingMediaRoutes .apply(this.ptr.getProxy(), arguments); }; MediaRouteProviderProxy.prototype.startObservingMediaRoutes = function(mediaSource) { var params = new MediaRouteProvider_StartObservingMediaRoutes_Params(); params.mediaSource = mediaSource; var builder = new codec.MessageV0Builder( kMediaRouteProvider_StartObservingMediaRoutes_Name, codec.align(MediaRouteProvider_StartObservingMediaRoutes_Params.encodedSize)); builder.encodeStruct(MediaRouteProvider_StartObservingMediaRoutes_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; MediaRouteProviderPtr.prototype.stopObservingMediaRoutes = function() { return MediaRouteProviderProxy.prototype.stopObservingMediaRoutes .apply(this.ptr.getProxy(), arguments); }; MediaRouteProviderProxy.prototype.stopObservingMediaRoutes = function(mediaSource) { var params = new MediaRouteProvider_StopObservingMediaRoutes_Params(); params.mediaSource = mediaSource; var builder = new codec.MessageV0Builder( kMediaRouteProvider_StopObservingMediaRoutes_Name, codec.align(MediaRouteProvider_StopObservingMediaRoutes_Params.encodedSize)); builder.encodeStruct(MediaRouteProvider_StopObservingMediaRoutes_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; MediaRouteProviderPtr.prototype.startListeningForRouteMessages = function() { return MediaRouteProviderProxy.prototype.startListeningForRouteMessages .apply(this.ptr.getProxy(), arguments); }; MediaRouteProviderProxy.prototype.startListeningForRouteMessages = function(routeId) { var params = new MediaRouteProvider_StartListeningForRouteMessages_Params(); params.routeId = routeId; var builder = new codec.MessageV0Builder( kMediaRouteProvider_StartListeningForRouteMessages_Name, codec.align(MediaRouteProvider_StartListeningForRouteMessages_Params.encodedSize)); builder.encodeStruct(MediaRouteProvider_StartListeningForRouteMessages_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; MediaRouteProviderPtr.prototype.stopListeningForRouteMessages = function() { return MediaRouteProviderProxy.prototype.stopListeningForRouteMessages .apply(this.ptr.getProxy(), arguments); }; MediaRouteProviderProxy.prototype.stopListeningForRouteMessages = function(routeId) { var params = new MediaRouteProvider_StopListeningForRouteMessages_Params(); params.routeId = routeId; var builder = new codec.MessageV0Builder( kMediaRouteProvider_StopListeningForRouteMessages_Name, codec.align(MediaRouteProvider_StopListeningForRouteMessages_Params.encodedSize)); builder.encodeStruct(MediaRouteProvider_StopListeningForRouteMessages_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; MediaRouteProviderPtr.prototype.detachRoute = function() { return MediaRouteProviderProxy.prototype.detachRoute .apply(this.ptr.getProxy(), arguments); }; MediaRouteProviderProxy.prototype.detachRoute = function(routeId) { var params = new MediaRouteProvider_DetachRoute_Params(); params.routeId = routeId; var builder = new codec.MessageV0Builder( kMediaRouteProvider_DetachRoute_Name, codec.align(MediaRouteProvider_DetachRoute_Params.encodedSize)); builder.encodeStruct(MediaRouteProvider_DetachRoute_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; MediaRouteProviderPtr.prototype.enableMdnsDiscovery = function() { return MediaRouteProviderProxy.prototype.enableMdnsDiscovery .apply(this.ptr.getProxy(), arguments); }; MediaRouteProviderProxy.prototype.enableMdnsDiscovery = function() { var params = new MediaRouteProvider_EnableMdnsDiscovery_Params(); var builder = new codec.MessageV0Builder( kMediaRouteProvider_EnableMdnsDiscovery_Name, codec.align(MediaRouteProvider_EnableMdnsDiscovery_Params.encodedSize)); builder.encodeStruct(MediaRouteProvider_EnableMdnsDiscovery_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; MediaRouteProviderPtr.prototype.updateMediaSinks = function() { return MediaRouteProviderProxy.prototype.updateMediaSinks .apply(this.ptr.getProxy(), arguments); }; MediaRouteProviderProxy.prototype.updateMediaSinks = function(mediaSource) { var params = new MediaRouteProvider_UpdateMediaSinks_Params(); params.mediaSource = mediaSource; var builder = new codec.MessageV0Builder( kMediaRouteProvider_UpdateMediaSinks_Name, codec.align(MediaRouteProvider_UpdateMediaSinks_Params.encodedSize)); builder.encodeStruct(MediaRouteProvider_UpdateMediaSinks_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; MediaRouteProviderPtr.prototype.searchSinks = function() { return MediaRouteProviderProxy.prototype.searchSinks .apply(this.ptr.getProxy(), arguments); }; MediaRouteProviderProxy.prototype.searchSinks = function(sinkId, mediaSource, searchCriteria) { var params = new MediaRouteProvider_SearchSinks_Params(); params.sinkId = sinkId; params.mediaSource = mediaSource; params.searchCriteria = searchCriteria; return new Promise(function(resolve, reject) { var builder = new codec.MessageV1Builder( kMediaRouteProvider_SearchSinks_Name, codec.align(MediaRouteProvider_SearchSinks_Params.encodedSize), codec.kMessageExpectsResponse, 0); builder.encodeStruct(MediaRouteProvider_SearchSinks_Params, params); var message = builder.finish(); this.receiver_.acceptAndExpectResponse(message).then(function(message) { var reader = new codec.MessageReader(message); var responseParams = reader.decodeStruct(MediaRouteProvider_SearchSinks_ResponseParams); resolve(responseParams); }).catch(function(result) { reject(Error("Connection error: " + result)); }); }.bind(this)); }; MediaRouteProviderPtr.prototype.provideSinks = function() { return MediaRouteProviderProxy.prototype.provideSinks .apply(this.ptr.getProxy(), arguments); }; MediaRouteProviderProxy.prototype.provideSinks = function(providerName, sinks) { var params = new MediaRouteProvider_ProvideSinks_Params(); params.providerName = providerName; params.sinks = sinks; var builder = new codec.MessageV0Builder( kMediaRouteProvider_ProvideSinks_Name, codec.align(MediaRouteProvider_ProvideSinks_Params.encodedSize)); builder.encodeStruct(MediaRouteProvider_ProvideSinks_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; MediaRouteProviderPtr.prototype.createMediaRouteController = function() { return MediaRouteProviderProxy.prototype.createMediaRouteController .apply(this.ptr.getProxy(), arguments); }; MediaRouteProviderProxy.prototype.createMediaRouteController = function(routeId, mediaController, observer) { var params = new MediaRouteProvider_CreateMediaRouteController_Params(); params.routeId = routeId; params.mediaController = mediaController; params.observer = observer; return new Promise(function(resolve, reject) { var builder = new codec.MessageV1Builder( kMediaRouteProvider_CreateMediaRouteController_Name, codec.align(MediaRouteProvider_CreateMediaRouteController_Params.encodedSize), codec.kMessageExpectsResponse, 0); builder.encodeStruct(MediaRouteProvider_CreateMediaRouteController_Params, params); var message = builder.finish(); this.receiver_.acceptAndExpectResponse(message).then(function(message) { var reader = new codec.MessageReader(message); var responseParams = reader.decodeStruct(MediaRouteProvider_CreateMediaRouteController_ResponseParams); resolve(responseParams); }).catch(function(result) { reject(Error("Connection error: " + result)); }); }.bind(this)); }; function MediaRouteProviderStub(delegate) { this.delegate_ = delegate; } MediaRouteProviderStub.prototype.createRoute = function(mediaSource, sinkId, originalPresentationId, origin, tabId, timeout, incognito) { return this.delegate_ && this.delegate_.createRoute && this.delegate_.createRoute(mediaSource, sinkId, originalPresentationId, origin, tabId, timeout, incognito); } MediaRouteProviderStub.prototype.joinRoute = function(mediaSource, presentationId, origin, tabId, timeout, incognito) { return this.delegate_ && this.delegate_.joinRoute && this.delegate_.joinRoute(mediaSource, presentationId, origin, tabId, timeout, incognito); } MediaRouteProviderStub.prototype.connectRouteByRouteId = function(mediaSource, routeId, presentationId, origin, tabId, timeout, incognito) { return this.delegate_ && this.delegate_.connectRouteByRouteId && this.delegate_.connectRouteByRouteId(mediaSource, routeId, presentationId, origin, tabId, timeout, incognito); } MediaRouteProviderStub.prototype.terminateRoute = function(routeId) { return this.delegate_ && this.delegate_.terminateRoute && this.delegate_.terminateRoute(routeId); } MediaRouteProviderStub.prototype.sendRouteMessage = function(mediaRouteId, message) { return this.delegate_ && this.delegate_.sendRouteMessage && this.delegate_.sendRouteMessage(mediaRouteId, message); } MediaRouteProviderStub.prototype.sendRouteBinaryMessage = function(mediaRouteId, data) { return this.delegate_ && this.delegate_.sendRouteBinaryMessage && this.delegate_.sendRouteBinaryMessage(mediaRouteId, data); } MediaRouteProviderStub.prototype.startObservingMediaSinks = function(mediaSource) { return this.delegate_ && this.delegate_.startObservingMediaSinks && this.delegate_.startObservingMediaSinks(mediaSource); } MediaRouteProviderStub.prototype.stopObservingMediaSinks = function(mediaSource) { return this.delegate_ && this.delegate_.stopObservingMediaSinks && this.delegate_.stopObservingMediaSinks(mediaSource); } MediaRouteProviderStub.prototype.startObservingMediaRoutes = function(mediaSource) { return this.delegate_ && this.delegate_.startObservingMediaRoutes && this.delegate_.startObservingMediaRoutes(mediaSource); } MediaRouteProviderStub.prototype.stopObservingMediaRoutes = function(mediaSource) { return this.delegate_ && this.delegate_.stopObservingMediaRoutes && this.delegate_.stopObservingMediaRoutes(mediaSource); } MediaRouteProviderStub.prototype.startListeningForRouteMessages = function(routeId) { return this.delegate_ && this.delegate_.startListeningForRouteMessages && this.delegate_.startListeningForRouteMessages(routeId); } MediaRouteProviderStub.prototype.stopListeningForRouteMessages = function(routeId) { return this.delegate_ && this.delegate_.stopListeningForRouteMessages && this.delegate_.stopListeningForRouteMessages(routeId); } MediaRouteProviderStub.prototype.detachRoute = function(routeId) { return this.delegate_ && this.delegate_.detachRoute && this.delegate_.detachRoute(routeId); } MediaRouteProviderStub.prototype.enableMdnsDiscovery = function() { return this.delegate_ && this.delegate_.enableMdnsDiscovery && this.delegate_.enableMdnsDiscovery(); } MediaRouteProviderStub.prototype.updateMediaSinks = function(mediaSource) { return this.delegate_ && this.delegate_.updateMediaSinks && this.delegate_.updateMediaSinks(mediaSource); } MediaRouteProviderStub.prototype.searchSinks = function(sinkId, mediaSource, searchCriteria) { return this.delegate_ && this.delegate_.searchSinks && this.delegate_.searchSinks(sinkId, mediaSource, searchCriteria); } MediaRouteProviderStub.prototype.provideSinks = function(providerName, sinks) { return this.delegate_ && this.delegate_.provideSinks && this.delegate_.provideSinks(providerName, sinks); } MediaRouteProviderStub.prototype.createMediaRouteController = function(routeId, mediaController, observer) { return this.delegate_ && this.delegate_.createMediaRouteController && this.delegate_.createMediaRouteController(routeId, mediaController, observer); } MediaRouteProviderStub.prototype.accept = function(message) { var reader = new codec.MessageReader(message); switch (reader.messageName) { case kMediaRouteProvider_StartObservingMediaSinks_Name: var params = reader.decodeStruct(MediaRouteProvider_StartObservingMediaSinks_Params); this.startObservingMediaSinks(params.mediaSource); return true; case kMediaRouteProvider_StopObservingMediaSinks_Name: var params = reader.decodeStruct(MediaRouteProvider_StopObservingMediaSinks_Params); this.stopObservingMediaSinks(params.mediaSource); return true; case kMediaRouteProvider_StartObservingMediaRoutes_Name: var params = reader.decodeStruct(MediaRouteProvider_StartObservingMediaRoutes_Params); this.startObservingMediaRoutes(params.mediaSource); return true; case kMediaRouteProvider_StopObservingMediaRoutes_Name: var params = reader.decodeStruct(MediaRouteProvider_StopObservingMediaRoutes_Params); this.stopObservingMediaRoutes(params.mediaSource); return true; case kMediaRouteProvider_StartListeningForRouteMessages_Name: var params = reader.decodeStruct(MediaRouteProvider_StartListeningForRouteMessages_Params); this.startListeningForRouteMessages(params.routeId); return true; case kMediaRouteProvider_StopListeningForRouteMessages_Name: var params = reader.decodeStruct(MediaRouteProvider_StopListeningForRouteMessages_Params); this.stopListeningForRouteMessages(params.routeId); return true; case kMediaRouteProvider_DetachRoute_Name: var params = reader.decodeStruct(MediaRouteProvider_DetachRoute_Params); this.detachRoute(params.routeId); return true; case kMediaRouteProvider_EnableMdnsDiscovery_Name: var params = reader.decodeStruct(MediaRouteProvider_EnableMdnsDiscovery_Params); this.enableMdnsDiscovery(); return true; case kMediaRouteProvider_UpdateMediaSinks_Name: var params = reader.decodeStruct(MediaRouteProvider_UpdateMediaSinks_Params); this.updateMediaSinks(params.mediaSource); return true; case kMediaRouteProvider_ProvideSinks_Name: var params = reader.decodeStruct(MediaRouteProvider_ProvideSinks_Params); this.provideSinks(params.providerName, params.sinks); return true; default: return false; } }; MediaRouteProviderStub.prototype.acceptWithResponder = function(message, responder) { var reader = new codec.MessageReader(message); switch (reader.messageName) { case kMediaRouteProvider_CreateRoute_Name: var params = reader.decodeStruct(MediaRouteProvider_CreateRoute_Params); this.createRoute(params.mediaSource, params.sinkId, params.originalPresentationId, params.origin, params.tabId, params.timeout, params.incognito).then(function(response) { var responseParams = new MediaRouteProvider_CreateRoute_ResponseParams(); responseParams.route = response.route; responseParams.errorText = response.errorText; responseParams.resultCode = response.resultCode; var builder = new codec.MessageV1Builder( kMediaRouteProvider_CreateRoute_Name, codec.align(MediaRouteProvider_CreateRoute_ResponseParams.encodedSize), codec.kMessageIsResponse, reader.requestID); builder.encodeStruct(MediaRouteProvider_CreateRoute_ResponseParams, responseParams); var message = builder.finish(); responder.accept(message); }); return true; case kMediaRouteProvider_JoinRoute_Name: var params = reader.decodeStruct(MediaRouteProvider_JoinRoute_Params); this.joinRoute(params.mediaSource, params.presentationId, params.origin, params.tabId, params.timeout, params.incognito).then(function(response) { var responseParams = new MediaRouteProvider_JoinRoute_ResponseParams(); responseParams.route = response.route; responseParams.errorText = response.errorText; responseParams.resultCode = response.resultCode; var builder = new codec.MessageV1Builder( kMediaRouteProvider_JoinRoute_Name, codec.align(MediaRouteProvider_JoinRoute_ResponseParams.encodedSize), codec.kMessageIsResponse, reader.requestID); builder.encodeStruct(MediaRouteProvider_JoinRoute_ResponseParams, responseParams); var message = builder.finish(); responder.accept(message); }); return true; case kMediaRouteProvider_ConnectRouteByRouteId_Name: var params = reader.decodeStruct(MediaRouteProvider_ConnectRouteByRouteId_Params); this.connectRouteByRouteId(params.mediaSource, params.routeId, params.presentationId, params.origin, params.tabId, params.timeout, params.incognito).then(function(response) { var responseParams = new MediaRouteProvider_ConnectRouteByRouteId_ResponseParams(); responseParams.route = response.route; responseParams.errorText = response.errorText; responseParams.resultCode = response.resultCode; var builder = new codec.MessageV1Builder( kMediaRouteProvider_ConnectRouteByRouteId_Name, codec.align(MediaRouteProvider_ConnectRouteByRouteId_ResponseParams.encodedSize), codec.kMessageIsResponse, reader.requestID); builder.encodeStruct(MediaRouteProvider_ConnectRouteByRouteId_ResponseParams, responseParams); var message = builder.finish(); responder.accept(message); }); return true; case kMediaRouteProvider_TerminateRoute_Name: var params = reader.decodeStruct(MediaRouteProvider_TerminateRoute_Params); this.terminateRoute(params.routeId).then(function(response) { var responseParams = new MediaRouteProvider_TerminateRoute_ResponseParams(); responseParams.errorText = response.errorText; responseParams.resultCode = response.resultCode; var builder = new codec.MessageV1Builder( kMediaRouteProvider_TerminateRoute_Name, codec.align(MediaRouteProvider_TerminateRoute_ResponseParams.encodedSize), codec.kMessageIsResponse, reader.requestID); builder.encodeStruct(MediaRouteProvider_TerminateRoute_ResponseParams, responseParams); var message = builder.finish(); responder.accept(message); }); return true; case kMediaRouteProvider_SendRouteMessage_Name: var params = reader.decodeStruct(MediaRouteProvider_SendRouteMessage_Params); this.sendRouteMessage(params.mediaRouteId, params.message).then(function(response) { var responseParams = new MediaRouteProvider_SendRouteMessage_ResponseParams(); responseParams.sent = response.sent; var builder = new codec.MessageV1Builder( kMediaRouteProvider_SendRouteMessage_Name, codec.align(MediaRouteProvider_SendRouteMessage_ResponseParams.encodedSize), codec.kMessageIsResponse, reader.requestID); builder.encodeStruct(MediaRouteProvider_SendRouteMessage_ResponseParams, responseParams); var message = builder.finish(); responder.accept(message); }); return true; case kMediaRouteProvider_SendRouteBinaryMessage_Name: var params = reader.decodeStruct(MediaRouteProvider_SendRouteBinaryMessage_Params); this.sendRouteBinaryMessage(params.mediaRouteId, params.data).then(function(response) { var responseParams = new MediaRouteProvider_SendRouteBinaryMessage_ResponseParams(); responseParams.sent = response.sent; var builder = new codec.MessageV1Builder( kMediaRouteProvider_SendRouteBinaryMessage_Name, codec.align(MediaRouteProvider_SendRouteBinaryMessage_ResponseParams.encodedSize), codec.kMessageIsResponse, reader.requestID); builder.encodeStruct(MediaRouteProvider_SendRouteBinaryMessage_ResponseParams, responseParams); var message = builder.finish(); responder.accept(message); }); return true; case kMediaRouteProvider_SearchSinks_Name: var params = reader.decodeStruct(MediaRouteProvider_SearchSinks_Params); this.searchSinks(params.sinkId, params.mediaSource, params.searchCriteria).then(function(response) { var responseParams = new MediaRouteProvider_SearchSinks_ResponseParams(); responseParams.sinkId = response.sinkId; var builder = new codec.MessageV1Builder( kMediaRouteProvider_SearchSinks_Name, codec.align(MediaRouteProvider_SearchSinks_ResponseParams.encodedSize), codec.kMessageIsResponse, reader.requestID); builder.encodeStruct(MediaRouteProvider_SearchSinks_ResponseParams, responseParams); var message = builder.finish(); responder.accept(message); }); return true; case kMediaRouteProvider_CreateMediaRouteController_Name: var params = reader.decodeStruct(MediaRouteProvider_CreateMediaRouteController_Params); this.createMediaRouteController(params.routeId, params.mediaController, params.observer).then(function(response) { var responseParams = new MediaRouteProvider_CreateMediaRouteController_ResponseParams(); responseParams.success = response.success; var builder = new codec.MessageV1Builder( kMediaRouteProvider_CreateMediaRouteController_Name, codec.align(MediaRouteProvider_CreateMediaRouteController_ResponseParams.encodedSize), codec.kMessageIsResponse, reader.requestID); builder.encodeStruct(MediaRouteProvider_CreateMediaRouteController_ResponseParams, responseParams); var message = builder.finish(); responder.accept(message); }); return true; default: return false; } }; function validateMediaRouteProviderRequest(messageValidator) { var message = messageValidator.message; var paramsClass = null; switch (message.getName()) { case kMediaRouteProvider_CreateRoute_Name: if (message.expectsResponse()) paramsClass = MediaRouteProvider_CreateRoute_Params; break; case kMediaRouteProvider_JoinRoute_Name: if (message.expectsResponse()) paramsClass = MediaRouteProvider_JoinRoute_Params; break; case kMediaRouteProvider_ConnectRouteByRouteId_Name: if (message.expectsResponse()) paramsClass = MediaRouteProvider_ConnectRouteByRouteId_Params; break; case kMediaRouteProvider_TerminateRoute_Name: if (message.expectsResponse()) paramsClass = MediaRouteProvider_TerminateRoute_Params; break; case kMediaRouteProvider_SendRouteMessage_Name: if (message.expectsResponse()) paramsClass = MediaRouteProvider_SendRouteMessage_Params; break; case kMediaRouteProvider_SendRouteBinaryMessage_Name: if (message.expectsResponse()) paramsClass = MediaRouteProvider_SendRouteBinaryMessage_Params; break; case kMediaRouteProvider_StartObservingMediaSinks_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = MediaRouteProvider_StartObservingMediaSinks_Params; break; case kMediaRouteProvider_StopObservingMediaSinks_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = MediaRouteProvider_StopObservingMediaSinks_Params; break; case kMediaRouteProvider_StartObservingMediaRoutes_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = MediaRouteProvider_StartObservingMediaRoutes_Params; break; case kMediaRouteProvider_StopObservingMediaRoutes_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = MediaRouteProvider_StopObservingMediaRoutes_Params; break; case kMediaRouteProvider_StartListeningForRouteMessages_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = MediaRouteProvider_StartListeningForRouteMessages_Params; break; case kMediaRouteProvider_StopListeningForRouteMessages_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = MediaRouteProvider_StopListeningForRouteMessages_Params; break; case kMediaRouteProvider_DetachRoute_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = MediaRouteProvider_DetachRoute_Params; break; case kMediaRouteProvider_EnableMdnsDiscovery_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = MediaRouteProvider_EnableMdnsDiscovery_Params; break; case kMediaRouteProvider_UpdateMediaSinks_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = MediaRouteProvider_UpdateMediaSinks_Params; break; case kMediaRouteProvider_SearchSinks_Name: if (message.expectsResponse()) paramsClass = MediaRouteProvider_SearchSinks_Params; break; case kMediaRouteProvider_ProvideSinks_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = MediaRouteProvider_ProvideSinks_Params; break; case kMediaRouteProvider_CreateMediaRouteController_Name: if (message.expectsResponse()) paramsClass = MediaRouteProvider_CreateMediaRouteController_Params; break; } if (paramsClass === null) return validator.validationError.NONE; return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes()); } function validateMediaRouteProviderResponse(messageValidator) { var message = messageValidator.message; var paramsClass = null; switch (message.getName()) { case kMediaRouteProvider_CreateRoute_Name: if (message.isResponse()) paramsClass = MediaRouteProvider_CreateRoute_ResponseParams; break; case kMediaRouteProvider_JoinRoute_Name: if (message.isResponse()) paramsClass = MediaRouteProvider_JoinRoute_ResponseParams; break; case kMediaRouteProvider_ConnectRouteByRouteId_Name: if (message.isResponse()) paramsClass = MediaRouteProvider_ConnectRouteByRouteId_ResponseParams; break; case kMediaRouteProvider_TerminateRoute_Name: if (message.isResponse()) paramsClass = MediaRouteProvider_TerminateRoute_ResponseParams; break; case kMediaRouteProvider_SendRouteMessage_Name: if (message.isResponse()) paramsClass = MediaRouteProvider_SendRouteMessage_ResponseParams; break; case kMediaRouteProvider_SendRouteBinaryMessage_Name: if (message.isResponse()) paramsClass = MediaRouteProvider_SendRouteBinaryMessage_ResponseParams; break; case kMediaRouteProvider_SearchSinks_Name: if (message.isResponse()) paramsClass = MediaRouteProvider_SearchSinks_ResponseParams; break; case kMediaRouteProvider_CreateMediaRouteController_Name: if (message.isResponse()) paramsClass = MediaRouteProvider_CreateMediaRouteController_ResponseParams; break; } if (paramsClass === null) return validator.validationError.NONE; return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes()); } var MediaRouteProvider = { name: 'media_router::mojom::MediaRouteProvider', kVersion: 0, ptrClass: MediaRouteProviderPtr, proxyClass: MediaRouteProviderProxy, stubClass: MediaRouteProviderStub, validateRequest: validateMediaRouteProviderRequest, validateResponse: validateMediaRouteProviderResponse, }; MediaRouteProvider.Id = {}; MediaRouteProvider.Id.EXTENSION = 0; MediaRouteProvider.Id.WIRED_DISPLAY = MediaRouteProvider.Id.EXTENSION + 1; MediaRouteProvider.Id.isKnownEnumValue = function(value) { switch (value) { case 0: case 1: return true; } return false; }; MediaRouteProvider.Id.validate = function(enumValue) { var isExtensible = false; if (isExtensible || this.isKnownEnumValue(enumValue)) return validator.validationError.NONE; return validator.validationError.UNKNOWN_ENUM_VALUE; }; MediaRouteProviderStub.prototype.validator = validateMediaRouteProviderRequest; MediaRouteProviderProxy.prototype.validator = validateMediaRouteProviderResponse; var kMediaRouter_RegisterMediaRouteProvider_Name = 1505294836; var kMediaRouter_OnSinksReceived_Name = 845103116; var kMediaRouter_OnIssue_Name = 1122644428; var kMediaRouter_OnRoutesUpdated_Name = 1954600429; var kMediaRouter_OnSinkAvailabilityUpdated_Name = 2122540235; var kMediaRouter_OnPresentationConnectionStateChanged_Name = 1609360068; var kMediaRouter_OnPresentationConnectionClosed_Name = 1622741397; var kMediaRouter_OnRouteMessagesReceived_Name = 763780902; var kMediaRouter_OnMediaRemoterCreated_Name = 489187334; function MediaRouterPtr(handleOrPtrInfo) { this.ptr = new bindings.InterfacePtrController(MediaRouter, handleOrPtrInfo); } function MediaRouterAssociatedPtr(associatedInterfacePtrInfo) { this.ptr = new associatedBindings.AssociatedInterfacePtrController( MediaRouter, associatedInterfacePtrInfo); } MediaRouterAssociatedPtr.prototype = Object.create(MediaRouterPtr.prototype); MediaRouterAssociatedPtr.prototype.constructor = MediaRouterAssociatedPtr; function MediaRouterProxy(receiver) { this.receiver_ = receiver; } MediaRouterPtr.prototype.registerMediaRouteProvider = function() { return MediaRouterProxy.prototype.registerMediaRouteProvider .apply(this.ptr.getProxy(), arguments); }; MediaRouterProxy.prototype.registerMediaRouteProvider = function(providerId, mediaRouterProvider) { var params = new MediaRouter_RegisterMediaRouteProvider_Params(); params.providerId = providerId; params.mediaRouterProvider = mediaRouterProvider; return new Promise(function(resolve, reject) { var builder = new codec.MessageV1Builder( kMediaRouter_RegisterMediaRouteProvider_Name, codec.align(MediaRouter_RegisterMediaRouteProvider_Params.encodedSize), codec.kMessageExpectsResponse, 0); builder.encodeStruct(MediaRouter_RegisterMediaRouteProvider_Params, params); var message = builder.finish(); this.receiver_.acceptAndExpectResponse(message).then(function(message) { var reader = new codec.MessageReader(message); var responseParams = reader.decodeStruct(MediaRouter_RegisterMediaRouteProvider_ResponseParams); resolve(responseParams); }).catch(function(result) { reject(Error("Connection error: " + result)); }); }.bind(this)); }; MediaRouterPtr.prototype.onSinksReceived = function() { return MediaRouterProxy.prototype.onSinksReceived .apply(this.ptr.getProxy(), arguments); }; MediaRouterProxy.prototype.onSinksReceived = function(providerId, mediaSource, sinks, origins) { var params = new MediaRouter_OnSinksReceived_Params(); params.providerId = providerId; params.mediaSource = mediaSource; params.sinks = sinks; params.origins = origins; var builder = new codec.MessageV0Builder( kMediaRouter_OnSinksReceived_Name, codec.align(MediaRouter_OnSinksReceived_Params.encodedSize)); builder.encodeStruct(MediaRouter_OnSinksReceived_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; MediaRouterPtr.prototype.onIssue = function() { return MediaRouterProxy.prototype.onIssue .apply(this.ptr.getProxy(), arguments); }; MediaRouterProxy.prototype.onIssue = function(issue) { var params = new MediaRouter_OnIssue_Params(); params.issue = issue; var builder = new codec.MessageV0Builder( kMediaRouter_OnIssue_Name, codec.align(MediaRouter_OnIssue_Params.encodedSize)); builder.encodeStruct(MediaRouter_OnIssue_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; MediaRouterPtr.prototype.onRoutesUpdated = function() { return MediaRouterProxy.prototype.onRoutesUpdated .apply(this.ptr.getProxy(), arguments); }; MediaRouterProxy.prototype.onRoutesUpdated = function(providerId, routes, mediaSource, joinableRouteIds) { var params = new MediaRouter_OnRoutesUpdated_Params(); params.providerId = providerId; params.routes = routes; params.mediaSource = mediaSource; params.joinableRouteIds = joinableRouteIds; var builder = new codec.MessageV0Builder( kMediaRouter_OnRoutesUpdated_Name, codec.align(MediaRouter_OnRoutesUpdated_Params.encodedSize)); builder.encodeStruct(MediaRouter_OnRoutesUpdated_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; MediaRouterPtr.prototype.onSinkAvailabilityUpdated = function() { return MediaRouterProxy.prototype.onSinkAvailabilityUpdated .apply(this.ptr.getProxy(), arguments); }; MediaRouterProxy.prototype.onSinkAvailabilityUpdated = function(providerId, availability) { var params = new MediaRouter_OnSinkAvailabilityUpdated_Params(); params.providerId = providerId; params.availability = availability; var builder = new codec.MessageV0Builder( kMediaRouter_OnSinkAvailabilityUpdated_Name, codec.align(MediaRouter_OnSinkAvailabilityUpdated_Params.encodedSize)); builder.encodeStruct(MediaRouter_OnSinkAvailabilityUpdated_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; MediaRouterPtr.prototype.onPresentationConnectionStateChanged = function() { return MediaRouterProxy.prototype.onPresentationConnectionStateChanged .apply(this.ptr.getProxy(), arguments); }; MediaRouterProxy.prototype.onPresentationConnectionStateChanged = function(routeId, state) { var params = new MediaRouter_OnPresentationConnectionStateChanged_Params(); params.routeId = routeId; params.state = state; var builder = new codec.MessageV0Builder( kMediaRouter_OnPresentationConnectionStateChanged_Name, codec.align(MediaRouter_OnPresentationConnectionStateChanged_Params.encodedSize)); builder.encodeStruct(MediaRouter_OnPresentationConnectionStateChanged_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; MediaRouterPtr.prototype.onPresentationConnectionClosed = function() { return MediaRouterProxy.prototype.onPresentationConnectionClosed .apply(this.ptr.getProxy(), arguments); }; MediaRouterProxy.prototype.onPresentationConnectionClosed = function(routeId, reason, message) { var params = new MediaRouter_OnPresentationConnectionClosed_Params(); params.routeId = routeId; params.reason = reason; params.message = message; var builder = new codec.MessageV0Builder( kMediaRouter_OnPresentationConnectionClosed_Name, codec.align(MediaRouter_OnPresentationConnectionClosed_Params.encodedSize)); builder.encodeStruct(MediaRouter_OnPresentationConnectionClosed_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; MediaRouterPtr.prototype.onRouteMessagesReceived = function() { return MediaRouterProxy.prototype.onRouteMessagesReceived .apply(this.ptr.getProxy(), arguments); }; MediaRouterProxy.prototype.onRouteMessagesReceived = function(routeId, messages) { var params = new MediaRouter_OnRouteMessagesReceived_Params(); params.routeId = routeId; params.messages = messages; var builder = new codec.MessageV0Builder( kMediaRouter_OnRouteMessagesReceived_Name, codec.align(MediaRouter_OnRouteMessagesReceived_Params.encodedSize)); builder.encodeStruct(MediaRouter_OnRouteMessagesReceived_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; MediaRouterPtr.prototype.onMediaRemoterCreated = function() { return MediaRouterProxy.prototype.onMediaRemoterCreated .apply(this.ptr.getProxy(), arguments); }; MediaRouterProxy.prototype.onMediaRemoterCreated = function(tabId, remoter, remotingSource) { var params = new MediaRouter_OnMediaRemoterCreated_Params(); params.tabId = tabId; params.remoter = remoter; params.remotingSource = remotingSource; var builder = new codec.MessageV0Builder( kMediaRouter_OnMediaRemoterCreated_Name, codec.align(MediaRouter_OnMediaRemoterCreated_Params.encodedSize)); builder.encodeStruct(MediaRouter_OnMediaRemoterCreated_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; function MediaRouterStub(delegate) { this.delegate_ = delegate; } MediaRouterStub.prototype.registerMediaRouteProvider = function(providerId, mediaRouterProvider) { return this.delegate_ && this.delegate_.registerMediaRouteProvider && this.delegate_.registerMediaRouteProvider(providerId, mediaRouterProvider); } MediaRouterStub.prototype.onSinksReceived = function(providerId, mediaSource, sinks, origins) { return this.delegate_ && this.delegate_.onSinksReceived && this.delegate_.onSinksReceived(providerId, mediaSource, sinks, origins); } MediaRouterStub.prototype.onIssue = function(issue) { return this.delegate_ && this.delegate_.onIssue && this.delegate_.onIssue(issue); } MediaRouterStub.prototype.onRoutesUpdated = function(providerId, routes, mediaSource, joinableRouteIds) { return this.delegate_ && this.delegate_.onRoutesUpdated && this.delegate_.onRoutesUpdated(providerId, routes, mediaSource, joinableRouteIds); } MediaRouterStub.prototype.onSinkAvailabilityUpdated = function(providerId, availability) { return this.delegate_ && this.delegate_.onSinkAvailabilityUpdated && this.delegate_.onSinkAvailabilityUpdated(providerId, availability); } MediaRouterStub.prototype.onPresentationConnectionStateChanged = function(routeId, state) { return this.delegate_ && this.delegate_.onPresentationConnectionStateChanged && this.delegate_.onPresentationConnectionStateChanged(routeId, state); } MediaRouterStub.prototype.onPresentationConnectionClosed = function(routeId, reason, message) { return this.delegate_ && this.delegate_.onPresentationConnectionClosed && this.delegate_.onPresentationConnectionClosed(routeId, reason, message); } MediaRouterStub.prototype.onRouteMessagesReceived = function(routeId, messages) { return this.delegate_ && this.delegate_.onRouteMessagesReceived && this.delegate_.onRouteMessagesReceived(routeId, messages); } MediaRouterStub.prototype.onMediaRemoterCreated = function(tabId, remoter, remotingSource) { return this.delegate_ && this.delegate_.onMediaRemoterCreated && this.delegate_.onMediaRemoterCreated(tabId, remoter, remotingSource); } MediaRouterStub.prototype.accept = function(message) { var reader = new codec.MessageReader(message); switch (reader.messageName) { case kMediaRouter_OnSinksReceived_Name: var params = reader.decodeStruct(MediaRouter_OnSinksReceived_Params); this.onSinksReceived(params.providerId, params.mediaSource, params.sinks, params.origins); return true; case kMediaRouter_OnIssue_Name: var params = reader.decodeStruct(MediaRouter_OnIssue_Params); this.onIssue(params.issue); return true; case kMediaRouter_OnRoutesUpdated_Name: var params = reader.decodeStruct(MediaRouter_OnRoutesUpdated_Params); this.onRoutesUpdated(params.providerId, params.routes, params.mediaSource, params.joinableRouteIds); return true; case kMediaRouter_OnSinkAvailabilityUpdated_Name: var params = reader.decodeStruct(MediaRouter_OnSinkAvailabilityUpdated_Params); this.onSinkAvailabilityUpdated(params.providerId, params.availability); return true; case kMediaRouter_OnPresentationConnectionStateChanged_Name: var params = reader.decodeStruct(MediaRouter_OnPresentationConnectionStateChanged_Params); this.onPresentationConnectionStateChanged(params.routeId, params.state); return true; case kMediaRouter_OnPresentationConnectionClosed_Name: var params = reader.decodeStruct(MediaRouter_OnPresentationConnectionClosed_Params); this.onPresentationConnectionClosed(params.routeId, params.reason, params.message); return true; case kMediaRouter_OnRouteMessagesReceived_Name: var params = reader.decodeStruct(MediaRouter_OnRouteMessagesReceived_Params); this.onRouteMessagesReceived(params.routeId, params.messages); return true; case kMediaRouter_OnMediaRemoterCreated_Name: var params = reader.decodeStruct(MediaRouter_OnMediaRemoterCreated_Params); this.onMediaRemoterCreated(params.tabId, params.remoter, params.remotingSource); return true; default: return false; } }; MediaRouterStub.prototype.acceptWithResponder = function(message, responder) { var reader = new codec.MessageReader(message); switch (reader.messageName) { case kMediaRouter_RegisterMediaRouteProvider_Name: var params = reader.decodeStruct(MediaRouter_RegisterMediaRouteProvider_Params); this.registerMediaRouteProvider(params.providerId, params.mediaRouterProvider).then(function(response) { var responseParams = new MediaRouter_RegisterMediaRouteProvider_ResponseParams(); responseParams.instanceId = response.instanceId; responseParams.config = response.config; var builder = new codec.MessageV1Builder( kMediaRouter_RegisterMediaRouteProvider_Name, codec.align(MediaRouter_RegisterMediaRouteProvider_ResponseParams.encodedSize), codec.kMessageIsResponse, reader.requestID); builder.encodeStruct(MediaRouter_RegisterMediaRouteProvider_ResponseParams, responseParams); var message = builder.finish(); responder.accept(message); }); return true; default: return false; } }; function validateMediaRouterRequest(messageValidator) { var message = messageValidator.message; var paramsClass = null; switch (message.getName()) { case kMediaRouter_RegisterMediaRouteProvider_Name: if (message.expectsResponse()) paramsClass = MediaRouter_RegisterMediaRouteProvider_Params; break; case kMediaRouter_OnSinksReceived_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = MediaRouter_OnSinksReceived_Params; break; case kMediaRouter_OnIssue_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = MediaRouter_OnIssue_Params; break; case kMediaRouter_OnRoutesUpdated_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = MediaRouter_OnRoutesUpdated_Params; break; case kMediaRouter_OnSinkAvailabilityUpdated_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = MediaRouter_OnSinkAvailabilityUpdated_Params; break; case kMediaRouter_OnPresentationConnectionStateChanged_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = MediaRouter_OnPresentationConnectionStateChanged_Params; break; case kMediaRouter_OnPresentationConnectionClosed_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = MediaRouter_OnPresentationConnectionClosed_Params; break; case kMediaRouter_OnRouteMessagesReceived_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = MediaRouter_OnRouteMessagesReceived_Params; break; case kMediaRouter_OnMediaRemoterCreated_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = MediaRouter_OnMediaRemoterCreated_Params; break; } if (paramsClass === null) return validator.validationError.NONE; return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes()); } function validateMediaRouterResponse(messageValidator) { var message = messageValidator.message; var paramsClass = null; switch (message.getName()) { case kMediaRouter_RegisterMediaRouteProvider_Name: if (message.isResponse()) paramsClass = MediaRouter_RegisterMediaRouteProvider_ResponseParams; break; } if (paramsClass === null) return validator.validationError.NONE; return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes()); } var MediaRouter = { name: 'media_router::mojom::MediaRouter', kVersion: 0, ptrClass: MediaRouterPtr, proxyClass: MediaRouterProxy, stubClass: MediaRouterStub, validateRequest: validateMediaRouterRequest, validateResponse: validateMediaRouterResponse, }; MediaRouter.SinkAvailability = {}; MediaRouter.SinkAvailability.UNAVAILABLE = 0; MediaRouter.SinkAvailability.PER_SOURCE = MediaRouter.SinkAvailability.UNAVAILABLE + 1; MediaRouter.SinkAvailability.AVAILABLE = MediaRouter.SinkAvailability.PER_SOURCE + 1; MediaRouter.SinkAvailability.isKnownEnumValue = function(value) { switch (value) { case 0: case 1: case 2: return true; } return false; }; MediaRouter.SinkAvailability.validate = function(enumValue) { var isExtensible = false; if (isExtensible || this.isKnownEnumValue(enumValue)) return validator.validationError.NONE; return validator.validationError.UNKNOWN_ENUM_VALUE; }; MediaRouter.PresentationConnectionState = {}; MediaRouter.PresentationConnectionState.CONNECTING = 0; MediaRouter.PresentationConnectionState.CONNECTED = MediaRouter.PresentationConnectionState.CONNECTING + 1; MediaRouter.PresentationConnectionState.CLOSED = MediaRouter.PresentationConnectionState.CONNECTED + 1; MediaRouter.PresentationConnectionState.TERMINATED = MediaRouter.PresentationConnectionState.CLOSED + 1; MediaRouter.PresentationConnectionState.isKnownEnumValue = function(value) { switch (value) { case 0: case 1: case 2: case 3: return true; } return false; }; MediaRouter.PresentationConnectionState.validate = function(enumValue) { var isExtensible = false; if (isExtensible || this.isKnownEnumValue(enumValue)) return validator.validationError.NONE; return validator.validationError.UNKNOWN_ENUM_VALUE; }; MediaRouter.PresentationConnectionCloseReason = {}; MediaRouter.PresentationConnectionCloseReason.CONNECTION_ERROR = 0; MediaRouter.PresentationConnectionCloseReason.CLOSED = MediaRouter.PresentationConnectionCloseReason.CONNECTION_ERROR + 1; MediaRouter.PresentationConnectionCloseReason.WENT_AWAY = MediaRouter.PresentationConnectionCloseReason.CLOSED + 1; MediaRouter.PresentationConnectionCloseReason.isKnownEnumValue = function(value) { switch (value) { case 0: case 1: case 2: return true; } return false; }; MediaRouter.PresentationConnectionCloseReason.validate = function(enumValue) { var isExtensible = false; if (isExtensible || this.isKnownEnumValue(enumValue)) return validator.validationError.NONE; return validator.validationError.UNKNOWN_ENUM_VALUE; }; MediaRouterStub.prototype.validator = validateMediaRouterRequest; MediaRouterProxy.prototype.validator = validateMediaRouterResponse; exports.SinkIconType = SinkIconType; exports.RouteControllerType = RouteControllerType; exports.RouteRequestResultCode = RouteRequestResultCode; exports.MediaSink = MediaSink; exports.DialMediaSink = DialMediaSink; exports.CastMediaSink = CastMediaSink; exports.MediaRoute = MediaRoute; exports.Issue = Issue; exports.RouteMessage = RouteMessage; exports.SinkSearchCriteria = SinkSearchCriteria; exports.MediaRouteProviderConfig = MediaRouteProviderConfig; exports.MediaSinkExtraData = MediaSinkExtraData; exports.MediaRouteProvider = MediaRouteProvider; exports.MediaRouteProviderPtr = MediaRouteProviderPtr; exports.MediaRouteProviderAssociatedPtr = MediaRouteProviderAssociatedPtr; exports.MediaRouter = MediaRouter; exports.MediaRouterPtr = MediaRouterPtr; exports.MediaRouterAssociatedPtr = MediaRouterAssociatedPtr; })();// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. 'use strict'; if ((typeof mojo === 'undefined') || !mojo.bindingsLibraryInitialized) { loadScript('mojo_bindings'); } mojo.config.autoLoadMojomDeps = false; loadScript('chrome/common/media_router/mojo/media_controller.mojom'); loadScript('chrome/common/media_router/mojo/media_router.mojom'); loadScript('chrome/common/media_router/mojo/media_status.mojom'); loadScript('extensions/common/mojo/keep_alive.mojom'); loadScript('media/mojo/interfaces/mirror_service_remoting.mojom'); loadScript('media/mojo/interfaces/remoting_common.mojom'); loadScript('mojo/common/time.mojom'); loadScript('net/interfaces/ip_address.mojom'); loadScript('net/interfaces/ip_endpoint.mojom'); loadScript('url/mojo/origin.mojom'); loadScript('url/mojo/url.mojom'); // The following adapter classes preserve backward compatibility for the media // router component extension. // TODO(crbug.com/787128): Remove these adapters. function assignFields(object, fields) { for(var field in fields) { if (object.hasOwnProperty(field)) object[field] = fields[field]; } } /** * Adapter for mediaRouter.mojom.DialMediaSink. * @constructor */ function DialMediaSinkAdapter(fields) { this.ip_address = null; this.model_name = null; this.app_url = null; assignFields(this, fields); } DialMediaSinkAdapter.fromNewVersion = function(other) { return new DialMediaSinkAdapter({ 'ip_address': IPAddressAdapter.fromNewVersion(other.ipAddress), 'model_name': other.modelName, 'app_url': other.appUrl, }); }; DialMediaSinkAdapter.prototype.toNewVersion = function() { return new mediaRouter.mojom.DialMediaSink({ 'ipAddress' : this.ip_address.toNewVersion(), 'modelName' : this.model_name, 'appUrl' : this.app_url, }); }; /** * Adapter for mediaRouter.mojom.CastMediaSink. * @constructor */ function CastMediaSinkAdapter(fields) { this.ip_endpoint = null; this.model_name = null; this.capabilities = 0; this.cast_channel_id = 0; assignFields(this, fields); } CastMediaSinkAdapter.fromNewVersion = function(other) { return new CastMediaSinkAdapter({ 'ip_endpoint': IPEndpointAdapter.fromNewVersion(other.ipEndpoint), 'model_name': other.modelName, 'capabilities': other.capabilities, 'cast_channel_id': other.castChannelId, }); }; CastMediaSinkAdapter.prototype.toNewVersion = function() { return new mediaRouter.mojom.CastMediaSink({ 'ipEndpoint': this.ip_endpoint.toNewVersion(), 'modelName': this.model_name, 'capabilities': this.capabilities, 'castChannelId': this.cast_channel_id, }); }; /** * Adapter for mediaRouter.mojom.HangoutsMediaStatusExtraData. * @constructor */ function HangoutsMediaStatusExtraDataAdapter(fields) { this.local_present = false; assignFields(this, fields); } HangoutsMediaStatusExtraDataAdapter.prototype.toNewVersion = function() { return new mediaRouter.mojom.HangoutsMediaStatusExtraData({ 'localPresent': this.local_present, }); }; /** * Adapter for net.interfaces.IPAddress. * @constructor */ function IPAddressAdapter(fields) { this.address_bytes = null; assignFields(this, fields); } IPAddressAdapter.fromNewVersion = function(other) { return new IPAddressAdapter({ 'address_bytes': other.addressBytes, }); }; IPAddressAdapter.prototype.toNewVersion = function() { return new net.interfaces.IPAddress({ 'addressBytes': this.address_bytes, }); }; /** * Adapter for net.interfaces.IPEndpoint. * @constructor */ function IPEndpointAdapter(fields) { this.address = null; this.port = 0; assignFields(this, fields); } IPEndpointAdapter.fromNewVersion = function(other) { return new IPEndpointAdapter({ 'address': IPAddressAdapter.fromNewVersion(other.address), 'port': other.port, }); }; IPEndpointAdapter.prototype.toNewVersion = function() { return new net.interfaces.IPEndpoint({ 'address': this.address.toNewVersion(), 'port': this.port, }); }; /** * Adapter for mediaRouter.mojom.MediaStatus. * @constructor */ function MediaStatusAdapter(fields) { this.title = null; this.description = null; this.can_play_pause = false; this.can_mute = false; this.can_set_volume = false; this.can_seek = false; this.is_muted = false; this.play_state = 0; this.volume = 0; this.duration = null; this.current_time = null; this.hangouts_extra_data = null; assignFields(this, fields); } MediaStatusAdapter.PlayState = mediaRouter.mojom.MediaStatus.PlayState; MediaStatusAdapter.prototype.toNewVersion = function() { return new mediaRouter.mojom.MediaStatus({ 'title': this.title, 'description': this.description, 'canPlayPause': this.can_play_pause, 'canMute': this.can_mute, 'canSetVolume': this.can_set_volume, 'canSeek': this.can_seek, 'isMuted': this.is_muted, 'playState': this.play_state, 'volume': this.volume, 'duration': this.duration, 'currentTime': this.current_time, 'hangoutsExtraData': this.hangouts_extra_data && this.hangouts_extra_data.toNewVersion(), }); }; /** * Adapter for media.mojom.RemotingSinkMetadata. * @constructor */ function RemotingSinkMetadataAdapter(fields) { this.features = null; this.audio_capabilities = null; this.video_capabilities = null; this.friendly_name = null; assignFields(this, fields); } RemotingSinkMetadataAdapter.fromNewVersion = function(other) { return new RemotingSinkMetadataAdapter({ 'features': other.features, 'audio_capabilities': other.audioCapabilities, 'video_capabilities': other.videoCapabilities, 'friendly_name': other.friendlyName, }); }; RemotingSinkMetadataAdapter.prototype.toNewVersion = function() { return new media.mojom.RemotingSinkMetadata({ 'features': this.features, 'audioCapabilities': this.audio_capabilities, 'videoCapabilities': this.video_capabilities, 'friendlyName': this.friendly_name, }); }; /** * Adapter for mediaRouter.mojom.MediaSink. * @constructor */ function MediaSinkAdapter(fields) { this.sink_id = null; this.name = null; this.description = null; this.domain = null; this.icon_type = 0; this.extra_data = null; assignFields(this, fields); } MediaSinkAdapter.fromNewVersion = function(other) { return new MediaSinkAdapter({ 'sink_id': other.sinkId, 'name': other.name, 'description': other.description, 'domain': other.domain, 'icon_type': other.iconType, 'extra_data': other.extraData && MediaSinkExtraDataAdapter.fromNewVersion(other.extraData), }); }; MediaSinkAdapter.prototype.toNewVersion = function() { return new mediaRouter.mojom.MediaSink({ 'sinkId': this.sink_id, 'name': this.name, 'description': this.description, 'domain': this.domain, 'iconType': this.icon_type, 'extraData': this.extra_data && this.extra_data.toNewVersion(), }); }; /** * Adapter for mediaRouter.mojom.MediaSinkExtraData. * @constructor */ function MediaSinkExtraDataAdapter(value) { this.$data = null; this.$tag = undefined; if (value == undefined) { return; } var keys = Object.keys(value); if (keys.length == 0) { return; } if (keys.length > 1) { throw new TypeError('You may set only one member on a union.'); } var fields = [ 'dial_media_sink', 'cast_media_sink', ]; if (fields.indexOf(keys[0]) < 0) { throw new ReferenceError(keys[0] + ' is not a MediaSinkExtraDataAdapter member.'); } this[keys[0]] = value[keys[0]]; } MediaSinkExtraDataAdapter.Tags = { dial_media_sink: 0, cast_media_sink: 1, }; Object.defineProperty(MediaSinkExtraDataAdapter.prototype, 'dial_media_sink', { get: function() { if (this.$tag != MediaSinkExtraDataAdapter.Tags.dial_media_sink) { throw new ReferenceError( 'MediaSinkExtraDataAdapter.dial_media_sink is not currently set.'); } return this.$data; }, set: function(value) { this.$tag = MediaSinkExtraDataAdapter.Tags.dial_media_sink; this.$data = value; } }); Object.defineProperty(MediaSinkExtraDataAdapter.prototype, 'cast_media_sink', { get: function() { if (this.$tag != MediaSinkExtraDataAdapter.Tags.cast_media_sink) { throw new ReferenceError( 'MediaSinkExtraDataAdapter.cast_media_sink is not currently set.'); } return this.$data; }, set: function(value) { this.$tag = MediaSinkExtraDataAdapter.Tags.cast_media_sink; this.$data = value; } }); MediaSinkExtraDataAdapter.fromNewVersion = function(other) { if (other.$tag == mediaRouter.mojom.MediaSinkExtraData.Tags.dialMediaSink) { return new MediaSinkExtraDataAdapter({ 'dial_media_sink': DialMediaSinkAdapter.fromNewVersion(other.dialMediaSink), }); } else { return new MediaSinkExtraDataAdapter({ 'cast_media_sink': CastMediaSinkAdapter.fromNewVersion(other.castMediaSink), }); } }; MediaSinkExtraDataAdapter.prototype.toNewVersion = function() { if (this.$tag == MediaSinkExtraDataAdapter.Tags.dial_media_sink) { return new mediaRouter.mojom.MediaSinkExtraData({ 'dialMediaSink': this.dial_media_sink.toNewVersion(), }); } else { return new mediaRouter.mojom.MediaSinkExtraData({ 'castMediaSink': this.cast_media_sink.toNewVersion(), }); } }; /** * Adapter for media.mojom.MirrorServiceRemoterPtr. * @constructor */ function MirrorServiceRemoterPtrAdapter(handleOrPtrInfo) { this.ptr = new mojo.InterfacePtrController(MirrorServiceRemoterAdapter, handleOrPtrInfo); } MirrorServiceRemoterPtrAdapter.prototype = Object.create(media.mojom.MirrorServiceRemoterPtr.prototype); MirrorServiceRemoterPtrAdapter.prototype.constructor = MirrorServiceRemoterPtrAdapter; MirrorServiceRemoterPtrAdapter.prototype.startDataStreams = function() { return MirrorServiceRemoterProxy.prototype.startDataStreams .apply(this.ptr.getProxy(), arguments).then(function(response) { return Promise.resolve({ 'audio_stream_id': response.audioStreamId, 'video_stream_id': response.videoStreamId, }); }); }; /** * Adapter for media.mojom.MirrorServiceRemoter.stubclass. * @constructor */ function MirrorServiceRemoterStubAdapter(delegate) { this.delegate_ = delegate; } MirrorServiceRemoterStubAdapter.prototype = Object.create( media.mojom.MirrorServiceRemoter.stubClass.prototype); MirrorServiceRemoterStubAdapter.prototype.constructor = MirrorServiceRemoterStubAdapter; MirrorServiceRemoterStubAdapter.prototype.startDataStreams = function(hasAudio, hasVideo) { return this.delegate_ && this.delegate_.startDataStreams && this.delegate_.startDataStreams(hasAudio, hasVideo).then( function(response) { return { 'audioStreamId': response.audio_stream_id, 'videoStreamId': response.video_stream_id, }; }); }; /** * Adapter for media.mojom.MirrorServiceRemoter. */ var MirrorServiceRemoterAdapter = { name: 'media::mojom::MirrorServiceRemoter', kVersion: 0, ptrClass: MirrorServiceRemoterPtrAdapter, proxyClass: media.mojom.MirrorServiceRemoter.proxyClass, stubClass: MirrorServiceRemoterStubAdapter, validateRequest: media.mojom.MirrorServiceRemoter.validateRequest, validateResponse: media.mojom.MirrorServiceRemoter.validateResponse, }; /** * Adapter for media.mojom.MirrorServiceRemotingSourcePtr. * @constructor */ function MirrorServiceRemotingSourcePtrAdapter(handleOrPtrInfo) { this.ptr = new mojo.InterfacePtrController(MirrorServiceRemotingSourceAdapter, handleOrPtrInfo); } MirrorServiceRemotingSourcePtrAdapter.prototype = Object.create(media.mojom.MirrorServiceRemotingSourcePtr.prototype); MirrorServiceRemotingSourcePtrAdapter.prototype.constructor = MirrorServiceRemotingSourcePtrAdapter; MirrorServiceRemotingSourcePtrAdapter.prototype.onSinkAvailable = function(metadata) { return this.ptr.getProxy().onSinkAvailable(metadata.toNewVersion()); }; /** * Adapter for media.mojom.MirrorServiceRemotingSource. */ var MirrorServiceRemotingSourceAdapter = { name: 'media::mojom::MirrorServiceRemotingSource', kVersion: 0, ptrClass: MirrorServiceRemotingSourcePtrAdapter, proxyClass: media.mojom.MirrorServiceRemotingSource.proxyClass, stubClass: null, validateRequest: media.mojom.MirrorServiceRemotingSource.validateRequest, validateResponse: null, }; /** * Adapter for mediaRouter.mojom.MediaStatusObserver. * @constructor */ function MediaStatusObserverPtrAdapter(handleOrPtrInfo) { this.ptr = new mojo.InterfacePtrController(MediaStatusObserverAdapter, handleOrPtrInfo); } MediaStatusObserverPtrAdapter.prototype = Object.create(mediaRouter.mojom.MediaStatusObserverPtr.prototype); MediaStatusObserverPtrAdapter.prototype.constructor = MediaStatusObserverPtrAdapter; MediaStatusObserverPtrAdapter.prototype.onMediaStatusUpdated = function(status) { return this.ptr.getProxy().onMediaStatusUpdated(status.toNewVersion()); }; /** * Adapter for mediaRouter.mojom.MediaStatusObserver. */ var MediaStatusObserverAdapter = { name: 'mediaRouter::mojom::MediaStatusObserver', kVersion: 0, ptrClass: MediaStatusObserverPtrAdapter, proxyClass: mediaRouter.mojom.MediaStatusObserver.proxyClass, stubClass: null, validateRequest: mediaRouter.mojom.MediaStatusObserver.validateRequest, validateResponse: null, }; /** * Converts a media sink to a MediaSink Mojo object. * @param {!MediaSink} sink A media sink. * @return {!mediaRouter.mojom.MediaSink} A Mojo MediaSink object. */ function sinkToMojo_(sink) { return new mediaRouter.mojom.MediaSink({ 'name': sink.friendlyName, 'description': sink.description, 'domain': sink.domain, 'sinkId': sink.id, 'iconType': sinkIconTypeToMojo(sink.iconType), 'providerId': mediaRouter.mojom.MediaRouteProvider.Id.EXTENSION, }); } /** * Converts a media sink's icon type to a MediaSink.IconType Mojo object. * @param {!MediaSink.IconType} type A media sink's icon type. * @return {!mediaRouter.mojom.MediaSink.IconType} A Mojo MediaSink.IconType * object. */ function sinkIconTypeToMojo(type) { switch (type) { case 'cast': return mediaRouter.mojom.SinkIconType.CAST; case 'cast_audio_group': return mediaRouter.mojom.SinkIconType.CAST_AUDIO_GROUP; case 'cast_audio': return mediaRouter.mojom.SinkIconType.CAST_AUDIO; case 'meeting': return mediaRouter.mojom.SinkIconType.MEETING; case 'hangout': return mediaRouter.mojom.SinkIconType.HANGOUT; case 'education': return mediaRouter.mojom.SinkIconType.EDUCATION; case 'generic': return mediaRouter.mojom.SinkIconType.GENERIC; default: console.error('Unknown sink icon type : ' + type); return mediaRouter.mojom.SinkIconType.GENERIC; } } /** * Returns a Mojo MediaRoute object given a MediaRoute and a * media sink name. * @param {!MediaRoute} route * @return {!mediaRouter.mojom.MediaRoute} */ function routeToMojo_(route) { return new mediaRouter.mojom.MediaRoute({ 'mediaRouteId': route.id, 'mediaSource': route.mediaSource, 'mediaSinkId': route.sinkId, 'description': route.description, 'iconUrl': route.iconUrl, 'isLocal': route.isLocal, 'forDisplay': route.forDisplay, 'isIncognito': route.offTheRecord, 'isLocalPresentation': route.isOffscreenPresentation, 'controllerType': route.controllerType, // Begin newly added properties, followed by the milestone they were // added. The guard should be safe to remove N+2 milestones later. 'presentationId': route.presentationId || '' // M64 }); } /** * Converts a route message to a RouteMessage Mojo object. * @param {!RouteMessage} message * @return {!mediaRouter.mojom.RouteMessage} A Mojo RouteMessage object. */ function messageToMojo_(message) { if ("string" == typeof message.message) { return new mediaRouter.mojom.RouteMessage({ 'type': mediaRouter.mojom.RouteMessage.Type.TEXT, 'message': message.message, }); } else { return new mediaRouter.mojom.RouteMessage({ 'type': mediaRouter.mojom.RouteMessage.Type.BINARY, 'data': message.message, }); } } /** * Converts presentation connection state to Mojo enum value. * @param {!string} state * @return {!mediaRouter.mojom.MediaRouter.PresentationConnectionState} */ function presentationConnectionStateToMojo_(state) { var PresentationConnectionState = mediaRouter.mojom.MediaRouter.PresentationConnectionState; switch (state) { case 'connecting': return PresentationConnectionState.CONNECTING; case 'connected': return PresentationConnectionState.CONNECTED; case 'closed': return PresentationConnectionState.CLOSED; case 'terminated': return PresentationConnectionState.TERMINATED; default: console.error('Unknown presentation connection state: ' + state); return PresentationConnectionState.TERMINATED; } } /** * Converts presentation connection close reason to Mojo enum value. * @param {!string} reason * @return {!mediaRouter.mojom.MediaRouter.PresentationConnectionCloseReason} */ function presentationConnectionCloseReasonToMojo_(reason) { var PresentationConnectionCloseReason = mediaRouter.mojom.MediaRouter.PresentationConnectionCloseReason; switch (reason) { case 'error': return PresentationConnectionCloseReason.CONNECTION_ERROR; case 'closed': return PresentationConnectionCloseReason.CLOSED; case 'went_away': return PresentationConnectionCloseReason.WENT_AWAY; default: console.error('Unknown presentation connection close reason : ' + reason); return PresentationConnectionCloseReason.CONNECTION_ERROR; } } /** * Converts string to Mojo origin. * @param {string|!url.mojom.Origin} origin * @return {!url.mojom.Origin} */ function stringToMojoOrigin_(origin) { if (origin instanceof url.mojom.Origin) { return origin; } var originUrl = new URL(origin); var mojoOrigin = {}; mojoOrigin.scheme = originUrl.protocol.replace(':', ''); mojoOrigin.host = originUrl.hostname; var port = originUrl.port ? Number.parseInt(originUrl.port) : 0; switch (mojoOrigin.scheme) { case 'http': mojoOrigin.port = port || 80; break; case 'https': mojoOrigin.port = port || 443; break; default: throw new Error('Scheme must be http or https'); } mojoOrigin.suborigin = ''; return new url.mojom.Origin(mojoOrigin); } /** * Parses the given route request Error object and converts it to the * corresponding result code. * @param {!Error} error * @return {!mediaRouter.mojom.RouteRequestResultCode} */ function getRouteRequestResultCode_(error) { return error.errorCode ? error.errorCode : mediaRouter.mojom.RouteRequestResultCode.UNKNOWN_ERROR; } /** * Creates and returns a successful route response from given route. * @param {!MediaRoute} route * @return {!Object} */ function toSuccessRouteResponse_(route) { return { route: routeToMojo_(route), resultCode: mediaRouter.mojom.RouteRequestResultCode.OK }; } /** * Creates and returns a error route response from given Error object. * @param {!Error} error * @return {!Object} */ function toErrorRouteResponse_(error) { return { errorText: error.message, resultCode: getRouteRequestResultCode_(error) }; } /** * Creates a new MediaRouter. * Converts a route struct to its Mojo form. * @param {!mediaRouter.mojom.MediaRouterPtr} service * @constructor */ function MediaRouter(service) { /** * The Mojo service proxy. Allows extension code to call methods that reside * in the browser. * @type {!mediaRouter.mojom.MediaRouterPtr} */ this.service_ = service; /** * The provider manager service delegate. Its methods are called by the * browser-resident Mojo service. * @type {!MediaRouter} */ this.mrpm_ = new MediaRouteProvider(this); /** * Handle to a KeepAlive service object, which prevents the extension from * being suspended as long as it remains in scope. * @type {boolean} */ this.keepAlive_ = null; /** * The bindings to bind the service delegate to the Mojo interface. * Object must remain in scope for the lifetime of the connection to * prevent the connection from closing automatically. * @type {!mojo.Binding} */ this.mediaRouteProviderBinding_ = new mojo.Binding( mediaRouter.mojom.MediaRouteProvider, this.mrpm_); } /** * Returns definitions of Mojo core and generated Mojom classes that can be * used directly by the component. * @return {!Object} * TODO(imcheng): We should export these along with MediaRouter. This requires * us to modify the component to handle multiple exports. When that logic is * baked in for a couple of milestones, we should be able to remove this * method. * TODO(imcheng): We should stop exporting mojo bindings classes that the * Media Router extension doesn't directly use, such as * mojo.AssociatedInterfacePtrInfo, mojo.InterfacePtrController and * mojo.interfaceControl. */ MediaRouter.prototype.getMojoExports = function() { return { AssociatedInterfacePtrInfo: mojo.AssociatedInterfacePtrInfo, Binding: mojo.Binding, DialMediaSink: DialMediaSinkAdapter, CastMediaSink: CastMediaSinkAdapter, HangoutsMediaRouteController: mediaRouter.mojom.HangoutsMediaRouteController, HangoutsMediaStatusExtraData: HangoutsMediaStatusExtraDataAdapter, IPAddress: IPAddressAdapter, IPEndpoint: IPEndpointAdapter, InterfacePtrController: mojo.InterfacePtrController, InterfacePtrInfo: mojo.InterfacePtrInfo, InterfaceRequest: mojo.InterfaceRequest, MediaController: mediaRouter.mojom.MediaController, MediaStatus: MediaStatusAdapter, MediaStatusObserverPtr: mediaRouter.mojom.MediaStatusObserverPtr, MirrorServiceRemoter: MirrorServiceRemoterAdapter, MirrorServiceRemoterPtr: MirrorServiceRemoterPtrAdapter, MirrorServiceRemotingSourcePtr: MirrorServiceRemotingSourcePtrAdapter, RemotingStopReason: media.mojom.RemotingStopReason, RemotingStartFailReason: media.mojom.RemotingStartFailReason, RemotingSinkFeature: media.mojom.RemotingSinkFeature, RemotingSinkAudioCapability: media.mojom.RemotingSinkAudioCapability, RemotingSinkVideoCapability: media.mojom.RemotingSinkVideoCapability, RemotingSinkMetadata: RemotingSinkMetadataAdapter, RouteControllerType: mediaRouter.mojom.RouteControllerType, Origin: url.mojom.Origin, Sink: MediaSinkAdapter, SinkExtraData: MediaSinkExtraDataAdapter, TimeDelta: mojo.common.mojom.TimeDelta, Url: url.mojom.Url, interfaceControl: mojo.interfaceControl, makeRequest: mojo.makeRequest, }; }; /** * Registers the Media Router Provider Manager with the Media Router. * @return {!Promise} Instance ID and config for the Media Router. */ MediaRouter.prototype.start = function() { return this.service_.registerMediaRouteProvider( mediaRouter.mojom.MediaRouteProvider.Id.EXTENSION, this.mediaRouteProviderBinding_.createInterfacePtrAndBind()).then( function(response) { return { 'instance_id': response.instanceId, 'config': { 'enable_dial_discovery': response.config.enableDialDiscovery, 'enable_cast_discovery': response.config.enableCastDiscovery, } }; }); } /** * Sets the service delegate methods. * @param {Object} handlers */ MediaRouter.prototype.setHandlers = function(handlers) { this.mrpm_.setHandlers(handlers); } /** * The keep alive status. * @return {boolean} */ MediaRouter.prototype.getKeepAlive = function() { return this.keepAlive_ != null; }; /** * Called by the provider manager when a sink list for a given source is * updated. * @param {!string} sourceUrn * @param {!Array} sinks * @param {!Array} origins */ MediaRouter.prototype.onSinksReceived = function(sourceUrn, sinks, origins) { // |origins| is a string array if the Media Router component extension version // is 59 or older. Without the stringToMojoOrigin_() conversion, clients using // those extension versions would see a crash shown in // https://crbug.com/787427. this.service_.onSinksReceived( mediaRouter.mojom.MediaRouteProvider.Id.EXTENSION, sourceUrn, sinks.map(sinkToMojo_), origins.map(stringToMojoOrigin_)); }; /** * Called by the provider manager when a sink is found to notify the MR of the * sink's ID. The actual sink will be returned through the normal sink list * update process, so this helps the MR identify the search result in the * list. * @param {string} pseudoSinkId ID of the pseudo sink that started the * search. * @param {string} sinkId ID of the newly-found sink. */ MediaRouter.prototype.onSearchSinkIdReceived = function( pseudoSinkId, sinkId) { this.service_.onSearchSinkIdReceived(pseudoSinkId, sinkId); }; /** * Called by the provider manager to keep the extension from suspending * if it enters a state where suspension is undesirable (e.g. there is an * active MediaRoute.) * If keepAlive is true, the extension is kept alive. * If keepAlive is false, the extension is allowed to suspend. * @param {boolean} keepAlive */ MediaRouter.prototype.setKeepAlive = function(keepAlive) { if (keepAlive === false && this.keepAlive_) { this.keepAlive_.ptr.reset(); this.keepAlive_ = null; } else if (keepAlive === true && !this.keepAlive_) { this.keepAlive_ = new extensions.KeepAlivePtr; Mojo.bindInterface(extensions.KeepAlive.name, mojo.makeRequest(this.keepAlive_).handle); } }; /** * Called by the provider manager to send an issue from a media route * provider to the Media Router, to show the user. * @param {!Object} issue The issue object. */ MediaRouter.prototype.onIssue = function(issue) { function issueSeverityToMojo_(severity) { switch (severity) { case 'fatal': return mediaRouter.mojom.Issue.Severity.FATAL; case 'warning': return mediaRouter.mojom.Issue.Severity.WARNING; case 'notification': return mediaRouter.mojom.Issue.Severity.NOTIFICATION; default: console.error('Unknown issue severity: ' + severity); return mediaRouter.mojom.Issue.Severity.NOTIFICATION; } } function issueActionToMojo_(action) { switch (action) { case 'dismiss': return mediaRouter.mojom.Issue.ActionType.DISMISS; case 'learn_more': return mediaRouter.mojom.Issue.ActionType.LEARN_MORE; default: console.error('Unknown issue action type : ' + action); return mediaRouter.mojom.Issue.ActionType.OK; } } var secondaryActions = (issue.secondaryActions || []).map(issueActionToMojo_); this.service_.onIssue(new mediaRouter.mojom.Issue({ 'routeId': issue.routeId || '', 'severity': issueSeverityToMojo_(issue.severity), 'title': issue.title, 'message': issue.message || '', 'defaultAction': issueActionToMojo_(issue.defaultAction), 'secondaryActions': secondaryActions, 'helpPageId': issue.helpPageId, 'isBlocking': issue.isBlocking })); }; /** * Called by the provider manager when the set of active routes * has been updated. * @param {!Array} routes The active set of media routes. * @param {string=} sourceUrn The sourceUrn associated with this route * query. * @param {Array=} joinableRouteIds The active set of joinable * media routes. */ MediaRouter.prototype.onRoutesUpdated = function( routes, sourceUrn = '', joinableRouteIds = []) { this.service_.onRoutesUpdated( mediaRouter.mojom.MediaRouteProvider.Id.EXTENSION, routes.map(routeToMojo_), sourceUrn, joinableRouteIds); }; /** * Called by the provider manager when sink availability has been updated. * @param {!mediaRouter.mojom.MediaRouter.SinkAvailability} availability * The new sink availability. */ MediaRouter.prototype.onSinkAvailabilityUpdated = function(availability) { this.service_.onSinkAvailabilityUpdated( mediaRouter.mojom.MediaRouteProvider.Id.EXTENSION, availability); }; /** * Called by the provider manager when the state of a presentation connected * to a route has changed. * @param {string} routeId * @param {string} state */ MediaRouter.prototype.onPresentationConnectionStateChanged = function(routeId, state) { this.service_.onPresentationConnectionStateChanged( routeId, presentationConnectionStateToMojo_(state)); }; /** * Called by the provider manager when the state of a presentation connected * to a route has closed. * @param {string} routeId * @param {string} reason * @param {string} message */ MediaRouter.prototype.onPresentationConnectionClosed = function(routeId, reason, message) { this.service_.onPresentationConnectionClosed( routeId, presentationConnectionCloseReasonToMojo_(reason), message); }; /** * @param {string} routeId * @param {!Array} mesages */ MediaRouter.prototype.onRouteMessagesReceived = function(routeId, messages) { this.service_.onRouteMessagesReceived( routeId, messages.map(messageToMojo_)); }; /** * @param {number} tabId * @param {!media.mojom.MirrorServiceRemoterPtr} remoter * @param {!mojo.InterfaceRequest} remotingSource */ MediaRouter.prototype.onMediaRemoterCreated = function(tabId, remoter, remotingSource) { this.service_.onMediaRemoterCreated( tabId, new media.mojom.MirrorServiceRemoterPtr(remoter.ptr.passInterface()), remotingSource); } /** * Object containing callbacks set by the provider manager. * * @constructor * @struct */ function MediaRouterHandlers() { /** * @type {function(!string, !string, !string, !string, !number)} */ this.createRoute = null; /** * @type {function(!string, !string, !string, !number)} */ this.joinRoute = null; /** * @type {function(string): Promise} */ this.terminateRoute = null; /** * @type {function(string)} */ this.startObservingMediaSinks = null; /** * @type {function(string)} */ this.stopObservingMediaSinks = null; /** * @type {function(string, string): Promise} */ this.sendRouteMessage = null; /** * @type {function(string, Uint8Array): Promise} */ this.sendRouteBinaryMessage = null; /** * @type {function(string)} */ this.startListeningForRouteMessages = null; /** * @type {function(string)} */ this.stopListeningForRouteMessages = null; /** * @type {function(string)} */ this.detachRoute = null; /** * @type {function()} */ this.startObservingMediaRoutes = null; /** * @type {function()} */ this.stopObservingMediaRoutes = null; /** * @type {function()} */ this.connectRouteByRouteId = null; /** * @type {function()} */ this.enableMdnsDiscovery = null; /** * @type {function()} */ this.updateMediaSinks = null; /** * @type {function(string, string, !SinkSearchCriteria): string} */ this.searchSinks = null; /** * @type {function()} */ this.provideSinks = null; /** * @type {function(string, !mojo.InterfaceRequest, * !mediaRouter.mojom.MediaStatusObserverPtr): !Promise} */ this.createMediaRouteController = null; }; /** * Routes calls from Media Router to the provider manager extension. * Registered with the MediaRouter stub. * @param {!MediaRouter} MediaRouter proxy to call into the * Media Router mojo interface. * @constructor */ function MediaRouteProvider(mediaRouter) { /** * Object containing JS callbacks into Provider Manager code. * @type {!MediaRouterHandlers} */ this.handlers_ = new MediaRouterHandlers(); /** * Proxy class to the browser's Media Router Mojo service. * @type {!MediaRouter} */ this.mediaRouter_ = mediaRouter; } /* * Sets the callback handler used to invoke methods in the provider manager. * * @param {!MediaRouterHandlers} handlers */ MediaRouteProvider.prototype.setHandlers = function(handlers) { this.handlers_ = handlers; var requiredHandlers = [ 'stopObservingMediaRoutes', 'startObservingMediaRoutes', 'sendRouteMessage', 'sendRouteBinaryMessage', 'startListeningForRouteMessages', 'stopListeningForRouteMessages', 'detachRoute', 'terminateRoute', 'joinRoute', 'createRoute', 'stopObservingMediaSinks', 'startObservingMediaRoutes', 'connectRouteByRouteId', 'enableMdnsDiscovery', 'updateMediaSinks', 'searchSinks', 'provideSinks', 'createMediaRouteController', 'onBeforeInvokeHandler' ]; requiredHandlers.forEach(function(nextHandler) { if (handlers[nextHandler] === undefined) { console.error(nextHandler + ' handler not registered.'); } }); } /** * Starts querying for sinks capable of displaying the media source * designated by |sourceUrn|. Results are returned by calling * OnSinksReceived. * @param {!string} sourceUrn */ MediaRouteProvider.prototype.startObservingMediaSinks = function(sourceUrn) { this.handlers_.onBeforeInvokeHandler(); this.handlers_.startObservingMediaSinks(sourceUrn); }; /** * Stops querying for sinks capable of displaying |sourceUrn|. * @param {!string} sourceUrn */ MediaRouteProvider.prototype.stopObservingMediaSinks = function(sourceUrn) { this.handlers_.onBeforeInvokeHandler(); this.handlers_.stopObservingMediaSinks(sourceUrn); }; /** * Requests that |sinkId| render the media referenced by |sourceUrn|. If the * request is from the Presentation API, then origin and tabId will * be populated. * @param {!string} sourceUrn Media source to render. * @param {!string} sinkId Media sink ID. * @param {!string} presentationId Presentation ID from the site * requesting presentation. TODO(mfoltz): Remove. * @param {!url.mojom.Origin} origin Origin of site requesting presentation. * @param {!number} tabId ID of tab requesting presentation. * @param {!mojo.common.mojom.TimeDelta} timeout If positive, the timeout * duration for the request. Otherwise, the default duration will be used. * @param {!boolean} incognito If true, the route is being requested by * an incognito profile. * @return {!Promise.} A Promise resolving to an object describing * the newly created media route, or rejecting with an error message on * failure. */ MediaRouteProvider.prototype.createRoute = function(sourceUrn, sinkId, presentationId, origin, tabId, timeout, incognito) { this.handlers_.onBeforeInvokeHandler(); return this.handlers_.createRoute( sourceUrn, sinkId, presentationId, origin, tabId, Math.floor(timeout.microseconds / 1000), incognito) .then(function(route) { return toSuccessRouteResponse_(route); }, function(err) { return toErrorRouteResponse_(err); }); }; /** * Handles a request via the Presentation API to join an existing route given * by |sourceUrn| and |presentationId|. |origin| and |tabId| are used for * validating same-origin/tab scope. * @param {!string} sourceUrn Media source to render. * @param {!string} presentationId Presentation ID to join. * @param {!url.mojom.Origin} origin Origin of site requesting join. * @param {!number} tabId ID of tab requesting join. * @param {!mojo.common.mojom.TimeDelta} timeout If positive, the timeout * duration for the request. Otherwise, the default duration will be used. * @param {!boolean} incognito If true, the route is being requested by * an incognito profile. * @return {!Promise.} A Promise resolving to an object describing * the newly created media route, or rejecting with an error message on * failure. */ MediaRouteProvider.prototype.joinRoute = function(sourceUrn, presentationId, origin, tabId, timeout, incognito) { this.handlers_.onBeforeInvokeHandler(); return this.handlers_.joinRoute( sourceUrn, presentationId, origin, tabId, Math.floor(timeout.microseconds / 1000), incognito) .then(function(route) { return toSuccessRouteResponse_(route); }, function(err) { return toErrorRouteResponse_(err); }); }; /** * Handles a request via the Presentation API to join an existing route given * by |sourceUrn| and |routeId|. |origin| and |tabId| are used for * validating same-origin/tab scope. * @param {!string} sourceUrn Media source to render. * @param {!string} routeId Route ID to join. * @param {!string} presentationId Presentation ID to join. * @param {!url.mojom.Origin} origin Origin of site requesting join. * @param {!number} tabId ID of tab requesting join. * @param {!mojo.common.mojom.TimeDelta} timeout If positive, the timeout * duration for the request. Otherwise, the default duration will be used. * @param {!boolean} incognito If true, the route is being requested by * an incognito profile. * @return {!Promise.} A Promise resolving to an object describing * the newly created media route, or rejecting with an error message on * failure. */ MediaRouteProvider.prototype.connectRouteByRouteId = function(sourceUrn, routeId, presentationId, origin, tabId, timeout, incognito) { this.handlers_.onBeforeInvokeHandler(); return this.handlers_.connectRouteByRouteId( sourceUrn, routeId, presentationId, origin, tabId, Math.floor(timeout.microseconds / 1000), incognito) .then(function(route) { return toSuccessRouteResponse_(route); }, function(err) { return toErrorRouteResponse_(err); }); }; /** * Terminates the route specified by |routeId|. * @param {!string} routeId * @return {!Promise} A Promise resolving to an object describing * the result of the terminate operation, or rejecting with an error * message and code if the operation failed. */ MediaRouteProvider.prototype.terminateRoute = function(routeId) { this.handlers_.onBeforeInvokeHandler(); return this.handlers_.terminateRoute(routeId).then( () => ({resultCode: mediaRouter.mojom.RouteRequestResultCode.OK}), (err) => toErrorRouteResponse_(err)); }; /** * Posts a message to the route designated by |routeId|. * @param {!string} routeId * @param {!string} message * @return {!Promise.} Resolved with true if the message was sent, * or false on failure. */ MediaRouteProvider.prototype.sendRouteMessage = function( routeId, message) { this.handlers_.onBeforeInvokeHandler(); return this.handlers_.sendRouteMessage(routeId, message) .then(function() { return {'sent': true}; }, function() { return {'sent': false}; }); }; /** * Sends a binary message to the route designated by |routeId|. * @param {!string} routeId * @param {!Array} data * @return {!Promise.} Resolved with true if the data was sent, * or false on failure. */ MediaRouteProvider.prototype.sendRouteBinaryMessage = function( routeId, data) { this.handlers_.onBeforeInvokeHandler(); return this.handlers_.sendRouteBinaryMessage(routeId, new Uint8Array(data)) .then(function() { return {'sent': true}; }, function() { return {'sent': false}; }); }; /** * Listen for messages from a route. * @param {!string} routeId */ MediaRouteProvider.prototype.startListeningForRouteMessages = function( routeId) { this.handlers_.onBeforeInvokeHandler(); this.handlers_.startListeningForRouteMessages(routeId); }; /** * @param {!string} routeId */ MediaRouteProvider.prototype.stopListeningForRouteMessages = function( routeId) { this.handlers_.onBeforeInvokeHandler(); this.handlers_.stopListeningForRouteMessages(routeId); }; /** * Indicates that the presentation connection that was connected to |routeId| * is no longer connected to it. * @param {!string} routeId */ MediaRouteProvider.prototype.detachRoute = function( routeId) { this.handlers_.detachRoute(routeId); }; /** * Requests that the provider manager start sending information about active * media routes to the Media Router. * @param {!string} sourceUrn */ MediaRouteProvider.prototype.startObservingMediaRoutes = function(sourceUrn) { this.handlers_.onBeforeInvokeHandler(); this.handlers_.startObservingMediaRoutes(sourceUrn); }; /** * Requests that the provider manager stop sending information about active * media routes to the Media Router. * @param {!string} sourceUrn */ MediaRouteProvider.prototype.stopObservingMediaRoutes = function(sourceUrn) { this.handlers_.onBeforeInvokeHandler(); this.handlers_.stopObservingMediaRoutes(sourceUrn); }; /** * Enables mDNS device discovery. */ MediaRouteProvider.prototype.enableMdnsDiscovery = function() { this.handlers_.onBeforeInvokeHandler(); this.handlers_.enableMdnsDiscovery(); }; /** * Requests that the provider manager update media sinks. * @param {!string} sourceUrn */ MediaRouteProvider.prototype.updateMediaSinks = function(sourceUrn) { this.handlers_.onBeforeInvokeHandler(); this.handlers_.updateMediaSinks(sourceUrn); }; /** * Requests that the provider manager search its providers for a sink matching * |searchCriteria| that is compatible with |sourceUrn|. If a sink is found * that can be used immediately for route creation, its ID is returned. * Otherwise the empty string is returned. * * @param {string} sinkId Sink ID of the pseudo sink generating the request. * @param {string} sourceUrn Media source to be used with the sink. * @param {!SinkSearchCriteria} searchCriteria Search criteria for the route * providers. * @return {!Promise.} A Promise resolving to either the * sink ID of the sink found by the search that can be used for route * creation, or the empty string if no route can be immediately created. */ MediaRouteProvider.prototype.searchSinks = function( sinkId, sourceUrn, searchCriteria) { this.handlers_.onBeforeInvokeHandler(); return this.handlers_.searchSinks(sinkId, sourceUrn, searchCriteria).then( sinkId => { return { 'sinkId': sinkId }; }, () => { return { 'sinkId': '' }; }); }; /** * Notifies the provider manager that MediaRouter has discovered a list of * sinks. * @param {string} providerName * @param {!Array} sinks */ MediaRouteProvider.prototype.provideSinks = function(providerName, sinks) { this.handlers_.onBeforeInvokeHandler(); this.handlers_.provideSinks(providerName, sinks.map(MediaSinkAdapter.fromNewVersion)); }; /** * Creates a controller for the given route and binds the given * InterfaceRequest to it, and registers an observer for media status updates * for the route. * @param {string} routeId * @param {!mojo.InterfaceRequest} controllerRequest * @param {!mediaRouter.mojom.MediaStatusObserverPtr} observer * @return {!Promise} Resolves to true if a controller * is created. Resolves to false if a controller cannot be created, or if * the controller is already bound. */ MediaRouteProvider.prototype.createMediaRouteController = function( routeId, controllerRequest, observer) { this.handlers_.onBeforeInvokeHandler(); return this.handlers_.createMediaRouteController( routeId, controllerRequest, new MediaStatusObserverPtrAdapter(observer.ptr.passInterface())).then( () => ({success: true}), e => ({success: false})); }; var ptr = new mediaRouter.mojom.MediaRouterPtr; Mojo.bindInterface(mediaRouter.mojom.MediaRouter.name, mojo.makeRequest(ptr).handle); exports.$set('returnValue', new MediaRouter(ptr)); // Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. 'use strict'; (function() { var mojomId = 'chrome/common/media_router/mojo/media_status.mojom'; if (mojo.internal.isMojomLoaded(mojomId)) { console.warn('The following mojom is loaded multiple times: ' + mojomId); return; } mojo.internal.markMojomLoaded(mojomId); var bindings = mojo; var associatedBindings = mojo; var codec = mojo.internal; var validator = mojo.internal; var exports = mojo.internal.exposeNamespace('mediaRouter.mojom'); var time$ = mojo.internal.exposeNamespace('mojo.common.mojom'); if (mojo.config.autoLoadMojomDeps) { mojo.internal.loadMojomIfNecessary( 'mojo/common/time.mojom', '../../../../mojo/common/time.mojom.js'); } function MediaStatus(values) { this.initDefaults_(); this.initFields_(values); } MediaStatus.PlayState = {}; MediaStatus.PlayState.PLAYING = 0; MediaStatus.PlayState.PAUSED = MediaStatus.PlayState.PLAYING + 1; MediaStatus.PlayState.BUFFERING = MediaStatus.PlayState.PAUSED + 1; MediaStatus.PlayState.isKnownEnumValue = function(value) { switch (value) { case 0: case 1: case 2: return true; } return false; }; MediaStatus.PlayState.validate = function(enumValue) { var isExtensible = false; if (isExtensible || this.isKnownEnumValue(enumValue)) return validator.validationError.NONE; return validator.validationError.UNKNOWN_ENUM_VALUE; }; MediaStatus.prototype.initDefaults_ = function() { this.title = null; this.description = null; this.canPlayPause = false; this.canMute = false; this.canSetVolume = false; this.canSeek = false; this.isMuted = false; this.playState = 0; this.volume = 0; this.duration = null; this.currentTime = null; this.hangoutsExtraData = null; }; MediaStatus.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaStatus.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 64} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaStatus.title err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false) if (err !== validator.validationError.NONE) return err; // validate MediaStatus.description err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false) if (err !== validator.validationError.NONE) return err; // validate MediaStatus.playState err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 20, MediaStatus.PlayState); if (err !== validator.validationError.NONE) return err; // validate MediaStatus.duration err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 32, time$.TimeDelta, false); if (err !== validator.validationError.NONE) return err; // validate MediaStatus.currentTime err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 40, time$.TimeDelta, false); if (err !== validator.validationError.NONE) return err; // validate MediaStatus.hangoutsExtraData err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 48, HangoutsMediaStatusExtraData, true); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaStatus.encodedSize = codec.kStructHeaderSize + 56; MediaStatus.decode = function(decoder) { var packed; var val = new MediaStatus(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.title = decoder.decodeStruct(codec.String); val.description = decoder.decodeStruct(codec.String); packed = decoder.readUint8(); val.canPlayPause = (packed >> 0) & 1 ? true : false; val.canMute = (packed >> 1) & 1 ? true : false; val.canSetVolume = (packed >> 2) & 1 ? true : false; val.canSeek = (packed >> 3) & 1 ? true : false; val.isMuted = (packed >> 4) & 1 ? true : false; decoder.skip(1); decoder.skip(1); decoder.skip(1); val.playState = decoder.decodeStruct(codec.Int32); val.volume = decoder.decodeStruct(codec.Float); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); val.duration = decoder.decodeStructPointer(time$.TimeDelta); val.currentTime = decoder.decodeStructPointer(time$.TimeDelta); val.hangoutsExtraData = decoder.decodeStructPointer(HangoutsMediaStatusExtraData); return val; }; MediaStatus.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaStatus.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.String, val.title); encoder.encodeStruct(codec.String, val.description); packed = 0; packed |= (val.canPlayPause & 1) << 0 packed |= (val.canMute & 1) << 1 packed |= (val.canSetVolume & 1) << 2 packed |= (val.canSeek & 1) << 3 packed |= (val.isMuted & 1) << 4 encoder.writeUint8(packed); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.encodeStruct(codec.Int32, val.playState); encoder.encodeStruct(codec.Float, val.volume); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.encodeStructPointer(time$.TimeDelta, val.duration); encoder.encodeStructPointer(time$.TimeDelta, val.currentTime); encoder.encodeStructPointer(HangoutsMediaStatusExtraData, val.hangoutsExtraData); }; function HangoutsMediaStatusExtraData(values) { this.initDefaults_(); this.initFields_(values); } HangoutsMediaStatusExtraData.prototype.initDefaults_ = function() { this.localPresent = false; }; HangoutsMediaStatusExtraData.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; HangoutsMediaStatusExtraData.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; HangoutsMediaStatusExtraData.encodedSize = codec.kStructHeaderSize + 8; HangoutsMediaStatusExtraData.decode = function(decoder) { var packed; var val = new HangoutsMediaStatusExtraData(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); packed = decoder.readUint8(); val.localPresent = (packed >> 0) & 1 ? true : false; decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); return val; }; HangoutsMediaStatusExtraData.encode = function(encoder, val) { var packed; encoder.writeUint32(HangoutsMediaStatusExtraData.encodedSize); encoder.writeUint32(0); packed = 0; packed |= (val.localPresent & 1) << 0 encoder.writeUint8(packed); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); }; function MediaStatusObserver_OnMediaStatusUpdated_Params(values) { this.initDefaults_(); this.initFields_(values); } MediaStatusObserver_OnMediaStatusUpdated_Params.prototype.initDefaults_ = function() { this.status = null; }; MediaStatusObserver_OnMediaStatusUpdated_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MediaStatusObserver_OnMediaStatusUpdated_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MediaStatusObserver_OnMediaStatusUpdated_Params.status err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 0, MediaStatus, false); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MediaStatusObserver_OnMediaStatusUpdated_Params.encodedSize = codec.kStructHeaderSize + 8; MediaStatusObserver_OnMediaStatusUpdated_Params.decode = function(decoder) { var packed; var val = new MediaStatusObserver_OnMediaStatusUpdated_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.status = decoder.decodeStructPointer(MediaStatus); return val; }; MediaStatusObserver_OnMediaStatusUpdated_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MediaStatusObserver_OnMediaStatusUpdated_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStructPointer(MediaStatus, val.status); }; var kMediaStatusObserver_OnMediaStatusUpdated_Name = 160151083; function MediaStatusObserverPtr(handleOrPtrInfo) { this.ptr = new bindings.InterfacePtrController(MediaStatusObserver, handleOrPtrInfo); } function MediaStatusObserverAssociatedPtr(associatedInterfacePtrInfo) { this.ptr = new associatedBindings.AssociatedInterfacePtrController( MediaStatusObserver, associatedInterfacePtrInfo); } MediaStatusObserverAssociatedPtr.prototype = Object.create(MediaStatusObserverPtr.prototype); MediaStatusObserverAssociatedPtr.prototype.constructor = MediaStatusObserverAssociatedPtr; function MediaStatusObserverProxy(receiver) { this.receiver_ = receiver; } MediaStatusObserverPtr.prototype.onMediaStatusUpdated = function() { return MediaStatusObserverProxy.prototype.onMediaStatusUpdated .apply(this.ptr.getProxy(), arguments); }; MediaStatusObserverProxy.prototype.onMediaStatusUpdated = function(status) { var params = new MediaStatusObserver_OnMediaStatusUpdated_Params(); params.status = status; var builder = new codec.MessageV0Builder( kMediaStatusObserver_OnMediaStatusUpdated_Name, codec.align(MediaStatusObserver_OnMediaStatusUpdated_Params.encodedSize)); builder.encodeStruct(MediaStatusObserver_OnMediaStatusUpdated_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; function MediaStatusObserverStub(delegate) { this.delegate_ = delegate; } MediaStatusObserverStub.prototype.onMediaStatusUpdated = function(status) { return this.delegate_ && this.delegate_.onMediaStatusUpdated && this.delegate_.onMediaStatusUpdated(status); } MediaStatusObserverStub.prototype.accept = function(message) { var reader = new codec.MessageReader(message); switch (reader.messageName) { case kMediaStatusObserver_OnMediaStatusUpdated_Name: var params = reader.decodeStruct(MediaStatusObserver_OnMediaStatusUpdated_Params); this.onMediaStatusUpdated(params.status); return true; default: return false; } }; MediaStatusObserverStub.prototype.acceptWithResponder = function(message, responder) { var reader = new codec.MessageReader(message); switch (reader.messageName) { default: return false; } }; function validateMediaStatusObserverRequest(messageValidator) { var message = messageValidator.message; var paramsClass = null; switch (message.getName()) { case kMediaStatusObserver_OnMediaStatusUpdated_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = MediaStatusObserver_OnMediaStatusUpdated_Params; break; } if (paramsClass === null) return validator.validationError.NONE; return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes()); } function validateMediaStatusObserverResponse(messageValidator) { return validator.validationError.NONE; } var MediaStatusObserver = { name: 'media_router::mojom::MediaStatusObserver', kVersion: 0, ptrClass: MediaStatusObserverPtr, proxyClass: MediaStatusObserverProxy, stubClass: MediaStatusObserverStub, validateRequest: validateMediaStatusObserverRequest, validateResponse: null, }; MediaStatusObserverStub.prototype.validator = validateMediaStatusObserverRequest; MediaStatusObserverProxy.prototype.validator = null; exports.MediaStatus = MediaStatus; exports.HangoutsMediaStatusExtraData = HangoutsMediaStatusExtraData; exports.MediaStatusObserver = MediaStatusObserver; exports.MediaStatusObserverPtr = MediaStatusObserverPtr; exports.MediaStatusObserverAssociatedPtr = MediaStatusObserverAssociatedPtr; })();// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. 'use strict'; (function() { var mojomId = 'mojo/common/time.mojom'; if (mojo.internal.isMojomLoaded(mojomId)) { console.warn('The following mojom is loaded multiple times: ' + mojomId); return; } mojo.internal.markMojomLoaded(mojomId); var bindings = mojo; var associatedBindings = mojo; var codec = mojo.internal; var validator = mojo.internal; var exports = mojo.internal.exposeNamespace('mojo.common.mojom'); function Time(values) { this.initDefaults_(); this.initFields_(values); } Time.prototype.initDefaults_ = function() { this.internalValue = 0; }; Time.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; Time.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; Time.encodedSize = codec.kStructHeaderSize + 8; Time.decode = function(decoder) { var packed; var val = new Time(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.internalValue = decoder.decodeStruct(codec.Int64); return val; }; Time.encode = function(encoder, val) { var packed; encoder.writeUint32(Time.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.Int64, val.internalValue); }; function TimeDelta(values) { this.initDefaults_(); this.initFields_(values); } TimeDelta.prototype.initDefaults_ = function() { this.microseconds = 0; }; TimeDelta.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; TimeDelta.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; TimeDelta.encodedSize = codec.kStructHeaderSize + 8; TimeDelta.decode = function(decoder) { var packed; var val = new TimeDelta(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.microseconds = decoder.decodeStruct(codec.Int64); return val; }; TimeDelta.encode = function(encoder, val) { var packed; encoder.writeUint32(TimeDelta.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.Int64, val.microseconds); }; function TimeTicks(values) { this.initDefaults_(); this.initFields_(values); } TimeTicks.prototype.initDefaults_ = function() { this.internalValue = 0; }; TimeTicks.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; TimeTicks.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; TimeTicks.encodedSize = codec.kStructHeaderSize + 8; TimeTicks.decode = function(decoder) { var packed; var val = new TimeTicks(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.internalValue = decoder.decodeStruct(codec.Int64); return val; }; TimeTicks.encode = function(encoder, val) { var packed; encoder.writeUint32(TimeTicks.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.Int64, val.internalValue); }; exports.Time = Time; exports.TimeDelta = TimeDelta; exports.TimeTicks = TimeTicks; })();// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. 'use strict'; (function() { var mojomId = 'net/interfaces/ip_address.mojom'; if (mojo.internal.isMojomLoaded(mojomId)) { console.warn('The following mojom is loaded multiple times: ' + mojomId); return; } mojo.internal.markMojomLoaded(mojomId); var bindings = mojo; var associatedBindings = mojo; var codec = mojo.internal; var validator = mojo.internal; var exports = mojo.internal.exposeNamespace('net.interfaces'); function IPAddress(values) { this.initDefaults_(); this.initFields_(values); } IPAddress.prototype.initDefaults_ = function() { this.addressBytes = null; }; IPAddress.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; IPAddress.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate IPAddress.addressBytes err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 0, 1, codec.Uint8, false, [0], 0); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; IPAddress.encodedSize = codec.kStructHeaderSize + 8; IPAddress.decode = function(decoder) { var packed; var val = new IPAddress(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.addressBytes = decoder.decodeArrayPointer(codec.Uint8); return val; }; IPAddress.encode = function(encoder, val) { var packed; encoder.writeUint32(IPAddress.encodedSize); encoder.writeUint32(0); encoder.encodeArrayPointer(codec.Uint8, val.addressBytes); }; exports.IPAddress = IPAddress; })();// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. 'use strict'; (function() { var mojomId = 'net/interfaces/ip_endpoint.mojom'; if (mojo.internal.isMojomLoaded(mojomId)) { console.warn('The following mojom is loaded multiple times: ' + mojomId); return; } mojo.internal.markMojomLoaded(mojomId); var bindings = mojo; var associatedBindings = mojo; var codec = mojo.internal; var validator = mojo.internal; var exports = mojo.internal.exposeNamespace('net.interfaces'); var ip_address$ = mojo.internal.exposeNamespace('net.interfaces'); if (mojo.config.autoLoadMojomDeps) { mojo.internal.loadMojomIfNecessary( 'net/interfaces/ip_address.mojom', 'ip_address.mojom.js'); } function IPEndPoint(values) { this.initDefaults_(); this.initFields_(values); } IPEndPoint.prototype.initDefaults_ = function() { this.address = null; this.port = 0; }; IPEndPoint.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; IPEndPoint.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 24} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate IPEndPoint.address err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 0, ip_address$.IPAddress, false); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; IPEndPoint.encodedSize = codec.kStructHeaderSize + 16; IPEndPoint.decode = function(decoder) { var packed; var val = new IPEndPoint(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.address = decoder.decodeStructPointer(ip_address$.IPAddress); val.port = decoder.decodeStruct(codec.Uint16); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); return val; }; IPEndPoint.encode = function(encoder, val) { var packed; encoder.writeUint32(IPEndPoint.encodedSize); encoder.writeUint32(0); encoder.encodeStructPointer(ip_address$.IPAddress, val.address); encoder.encodeStruct(codec.Uint16, val.port); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); }; exports.IPEndPoint = IPEndPoint; })();// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. 'use strict'; (function() { var mojomId = 'url/mojo/origin.mojom'; if (mojo.internal.isMojomLoaded(mojomId)) { console.warn('The following mojom is loaded multiple times: ' + mojomId); return; } mojo.internal.markMojomLoaded(mojomId); var bindings = mojo; var associatedBindings = mojo; var codec = mojo.internal; var validator = mojo.internal; var exports = mojo.internal.exposeNamespace('url.mojom'); function Origin(values) { this.initDefaults_(); this.initFields_(values); } Origin.prototype.initDefaults_ = function() { this.scheme = null; this.host = null; this.port = 0; this.unique = false; this.suborigin = null; }; Origin.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; Origin.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 40} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate Origin.scheme err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false) if (err !== validator.validationError.NONE) return err; // validate Origin.host err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 8, false) if (err !== validator.validationError.NONE) return err; // validate Origin.suborigin err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 24, false) if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; Origin.encodedSize = codec.kStructHeaderSize + 32; Origin.decode = function(decoder) { var packed; var val = new Origin(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.scheme = decoder.decodeStruct(codec.String); val.host = decoder.decodeStruct(codec.String); val.port = decoder.decodeStruct(codec.Uint16); packed = decoder.readUint8(); val.unique = (packed >> 0) & 1 ? true : false; decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); val.suborigin = decoder.decodeStruct(codec.String); return val; }; Origin.encode = function(encoder, val) { var packed; encoder.writeUint32(Origin.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.String, val.scheme); encoder.encodeStruct(codec.String, val.host); encoder.encodeStruct(codec.Uint16, val.port); packed = 0; packed |= (val.unique & 1) << 0 encoder.writeUint8(packed); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.encodeStruct(codec.String, val.suborigin); }; exports.Origin = Origin; })();// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. 'use strict'; (function() { var mojomId = 'url/mojo/url.mojom'; if (mojo.internal.isMojomLoaded(mojomId)) { console.warn('The following mojom is loaded multiple times: ' + mojomId); return; } mojo.internal.markMojomLoaded(mojomId); var bindings = mojo; var associatedBindings = mojo; var codec = mojo.internal; var validator = mojo.internal; var exports = mojo.internal.exposeNamespace('url.mojom'); function Url(values) { this.initDefaults_(); this.initFields_(values); } Url.prototype.initDefaults_ = function() { this.url = null; }; Url.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; Url.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate Url.url err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 0, false) if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; Url.encodedSize = codec.kStructHeaderSize + 8; Url.decode = function(decoder) { var packed; var val = new Url(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.url = decoder.decodeStruct(codec.String); return val; }; Url.encode = function(encoder, val) { var packed; encoder.writeUint32(Url.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.String, val.url); }; exports.Url = Url; })();// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. 'use strict'; (function() { var mojomId = 'media/mojo/interfaces/mirror_service_remoting.mojom'; if (mojo.internal.isMojomLoaded(mojomId)) { console.warn('The following mojom is loaded multiple times: ' + mojomId); return; } mojo.internal.markMojomLoaded(mojomId); var bindings = mojo; var associatedBindings = mojo; var codec = mojo.internal; var validator = mojo.internal; var exports = mojo.internal.exposeNamespace('media.mojom'); var remoting_common$ = mojo.internal.exposeNamespace('media.mojom'); if (mojo.config.autoLoadMojomDeps) { mojo.internal.loadMojomIfNecessary( 'media/mojo/interfaces/remoting_common.mojom', 'remoting_common.mojom.js'); } function MirrorServiceRemoter_Start_Params(values) { this.initDefaults_(); this.initFields_(values); } MirrorServiceRemoter_Start_Params.prototype.initDefaults_ = function() { }; MirrorServiceRemoter_Start_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MirrorServiceRemoter_Start_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 8} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MirrorServiceRemoter_Start_Params.encodedSize = codec.kStructHeaderSize + 0; MirrorServiceRemoter_Start_Params.decode = function(decoder) { var packed; var val = new MirrorServiceRemoter_Start_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); return val; }; MirrorServiceRemoter_Start_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MirrorServiceRemoter_Start_Params.encodedSize); encoder.writeUint32(0); }; function MirrorServiceRemoter_StartDataStreams_Params(values) { this.initDefaults_(); this.initFields_(values); } MirrorServiceRemoter_StartDataStreams_Params.prototype.initDefaults_ = function() { this.hasAudio = false; this.hasVideo = false; }; MirrorServiceRemoter_StartDataStreams_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MirrorServiceRemoter_StartDataStreams_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MirrorServiceRemoter_StartDataStreams_Params.encodedSize = codec.kStructHeaderSize + 8; MirrorServiceRemoter_StartDataStreams_Params.decode = function(decoder) { var packed; var val = new MirrorServiceRemoter_StartDataStreams_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); packed = decoder.readUint8(); val.hasAudio = (packed >> 0) & 1 ? true : false; val.hasVideo = (packed >> 1) & 1 ? true : false; decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); return val; }; MirrorServiceRemoter_StartDataStreams_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MirrorServiceRemoter_StartDataStreams_Params.encodedSize); encoder.writeUint32(0); packed = 0; packed |= (val.hasAudio & 1) << 0 packed |= (val.hasVideo & 1) << 1 encoder.writeUint8(packed); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); }; function MirrorServiceRemoter_StartDataStreams_ResponseParams(values) { this.initDefaults_(); this.initFields_(values); } MirrorServiceRemoter_StartDataStreams_ResponseParams.prototype.initDefaults_ = function() { this.audioStreamId = 0; this.videoStreamId = 0; }; MirrorServiceRemoter_StartDataStreams_ResponseParams.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MirrorServiceRemoter_StartDataStreams_ResponseParams.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MirrorServiceRemoter_StartDataStreams_ResponseParams.encodedSize = codec.kStructHeaderSize + 8; MirrorServiceRemoter_StartDataStreams_ResponseParams.decode = function(decoder) { var packed; var val = new MirrorServiceRemoter_StartDataStreams_ResponseParams(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.audioStreamId = decoder.decodeStruct(codec.Int32); val.videoStreamId = decoder.decodeStruct(codec.Int32); return val; }; MirrorServiceRemoter_StartDataStreams_ResponseParams.encode = function(encoder, val) { var packed; encoder.writeUint32(MirrorServiceRemoter_StartDataStreams_ResponseParams.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.Int32, val.audioStreamId); encoder.encodeStruct(codec.Int32, val.videoStreamId); }; function MirrorServiceRemoter_Stop_Params(values) { this.initDefaults_(); this.initFields_(values); } MirrorServiceRemoter_Stop_Params.prototype.initDefaults_ = function() { this.reason = 0; }; MirrorServiceRemoter_Stop_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MirrorServiceRemoter_Stop_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MirrorServiceRemoter_Stop_Params.reason err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 0, remoting_common$.RemotingStopReason); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MirrorServiceRemoter_Stop_Params.encodedSize = codec.kStructHeaderSize + 8; MirrorServiceRemoter_Stop_Params.decode = function(decoder) { var packed; var val = new MirrorServiceRemoter_Stop_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.reason = decoder.decodeStruct(codec.Int32); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); return val; }; MirrorServiceRemoter_Stop_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MirrorServiceRemoter_Stop_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.Int32, val.reason); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); }; function MirrorServiceRemoter_SendMessageToSink_Params(values) { this.initDefaults_(); this.initFields_(values); } MirrorServiceRemoter_SendMessageToSink_Params.prototype.initDefaults_ = function() { this.message = null; }; MirrorServiceRemoter_SendMessageToSink_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MirrorServiceRemoter_SendMessageToSink_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MirrorServiceRemoter_SendMessageToSink_Params.message err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 0, 1, codec.Uint8, false, [0], 0); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MirrorServiceRemoter_SendMessageToSink_Params.encodedSize = codec.kStructHeaderSize + 8; MirrorServiceRemoter_SendMessageToSink_Params.decode = function(decoder) { var packed; var val = new MirrorServiceRemoter_SendMessageToSink_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.message = decoder.decodeArrayPointer(codec.Uint8); return val; }; MirrorServiceRemoter_SendMessageToSink_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MirrorServiceRemoter_SendMessageToSink_Params.encodedSize); encoder.writeUint32(0); encoder.encodeArrayPointer(codec.Uint8, val.message); }; function MirrorServiceRemoter_EstimateTransmissionCapacity_Params(values) { this.initDefaults_(); this.initFields_(values); } MirrorServiceRemoter_EstimateTransmissionCapacity_Params.prototype.initDefaults_ = function() { }; MirrorServiceRemoter_EstimateTransmissionCapacity_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MirrorServiceRemoter_EstimateTransmissionCapacity_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 8} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MirrorServiceRemoter_EstimateTransmissionCapacity_Params.encodedSize = codec.kStructHeaderSize + 0; MirrorServiceRemoter_EstimateTransmissionCapacity_Params.decode = function(decoder) { var packed; var val = new MirrorServiceRemoter_EstimateTransmissionCapacity_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); return val; }; MirrorServiceRemoter_EstimateTransmissionCapacity_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MirrorServiceRemoter_EstimateTransmissionCapacity_Params.encodedSize); encoder.writeUint32(0); }; function MirrorServiceRemoter_EstimateTransmissionCapacity_ResponseParams(values) { this.initDefaults_(); this.initFields_(values); } MirrorServiceRemoter_EstimateTransmissionCapacity_ResponseParams.prototype.initDefaults_ = function() { this.rate = 0; }; MirrorServiceRemoter_EstimateTransmissionCapacity_ResponseParams.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MirrorServiceRemoter_EstimateTransmissionCapacity_ResponseParams.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MirrorServiceRemoter_EstimateTransmissionCapacity_ResponseParams.encodedSize = codec.kStructHeaderSize + 8; MirrorServiceRemoter_EstimateTransmissionCapacity_ResponseParams.decode = function(decoder) { var packed; var val = new MirrorServiceRemoter_EstimateTransmissionCapacity_ResponseParams(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.rate = decoder.decodeStruct(codec.Double); return val; }; MirrorServiceRemoter_EstimateTransmissionCapacity_ResponseParams.encode = function(encoder, val) { var packed; encoder.writeUint32(MirrorServiceRemoter_EstimateTransmissionCapacity_ResponseParams.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.Double, val.rate); }; function MirrorServiceRemotingSource_OnSinkAvailable_Params(values) { this.initDefaults_(); this.initFields_(values); } MirrorServiceRemotingSource_OnSinkAvailable_Params.prototype.initDefaults_ = function() { this.metadata = null; }; MirrorServiceRemotingSource_OnSinkAvailable_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MirrorServiceRemotingSource_OnSinkAvailable_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MirrorServiceRemotingSource_OnSinkAvailable_Params.metadata err = messageValidator.validateStructPointer(offset + codec.kStructHeaderSize + 0, remoting_common$.RemotingSinkMetadata, false); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MirrorServiceRemotingSource_OnSinkAvailable_Params.encodedSize = codec.kStructHeaderSize + 8; MirrorServiceRemotingSource_OnSinkAvailable_Params.decode = function(decoder) { var packed; var val = new MirrorServiceRemotingSource_OnSinkAvailable_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.metadata = decoder.decodeStructPointer(remoting_common$.RemotingSinkMetadata); return val; }; MirrorServiceRemotingSource_OnSinkAvailable_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MirrorServiceRemotingSource_OnSinkAvailable_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStructPointer(remoting_common$.RemotingSinkMetadata, val.metadata); }; function MirrorServiceRemotingSource_OnMessageFromSink_Params(values) { this.initDefaults_(); this.initFields_(values); } MirrorServiceRemotingSource_OnMessageFromSink_Params.prototype.initDefaults_ = function() { this.message = null; }; MirrorServiceRemotingSource_OnMessageFromSink_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MirrorServiceRemotingSource_OnMessageFromSink_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MirrorServiceRemotingSource_OnMessageFromSink_Params.message err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 0, 1, codec.Uint8, false, [0], 0); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MirrorServiceRemotingSource_OnMessageFromSink_Params.encodedSize = codec.kStructHeaderSize + 8; MirrorServiceRemotingSource_OnMessageFromSink_Params.decode = function(decoder) { var packed; var val = new MirrorServiceRemotingSource_OnMessageFromSink_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.message = decoder.decodeArrayPointer(codec.Uint8); return val; }; MirrorServiceRemotingSource_OnMessageFromSink_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MirrorServiceRemotingSource_OnMessageFromSink_Params.encodedSize); encoder.writeUint32(0); encoder.encodeArrayPointer(codec.Uint8, val.message); }; function MirrorServiceRemotingSource_OnStopped_Params(values) { this.initDefaults_(); this.initFields_(values); } MirrorServiceRemotingSource_OnStopped_Params.prototype.initDefaults_ = function() { this.reason = 0; }; MirrorServiceRemotingSource_OnStopped_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MirrorServiceRemotingSource_OnStopped_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 16} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate MirrorServiceRemotingSource_OnStopped_Params.reason err = messageValidator.validateEnum(offset + codec.kStructHeaderSize + 0, remoting_common$.RemotingStopReason); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MirrorServiceRemotingSource_OnStopped_Params.encodedSize = codec.kStructHeaderSize + 8; MirrorServiceRemotingSource_OnStopped_Params.decode = function(decoder) { var packed; var val = new MirrorServiceRemotingSource_OnStopped_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.reason = decoder.decodeStruct(codec.Int32); decoder.skip(1); decoder.skip(1); decoder.skip(1); decoder.skip(1); return val; }; MirrorServiceRemotingSource_OnStopped_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MirrorServiceRemotingSource_OnStopped_Params.encodedSize); encoder.writeUint32(0); encoder.encodeStruct(codec.Int32, val.reason); encoder.skip(1); encoder.skip(1); encoder.skip(1); encoder.skip(1); }; function MirrorServiceRemotingSource_OnError_Params(values) { this.initDefaults_(); this.initFields_(values); } MirrorServiceRemotingSource_OnError_Params.prototype.initDefaults_ = function() { }; MirrorServiceRemotingSource_OnError_Params.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; MirrorServiceRemotingSource_OnError_Params.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 8} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; MirrorServiceRemotingSource_OnError_Params.encodedSize = codec.kStructHeaderSize + 0; MirrorServiceRemotingSource_OnError_Params.decode = function(decoder) { var packed; var val = new MirrorServiceRemotingSource_OnError_Params(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); return val; }; MirrorServiceRemotingSource_OnError_Params.encode = function(encoder, val) { var packed; encoder.writeUint32(MirrorServiceRemotingSource_OnError_Params.encodedSize); encoder.writeUint32(0); }; var kMirrorServiceRemoter_Start_Name = 2076494608; var kMirrorServiceRemoter_StartDataStreams_Name = 216222009; var kMirrorServiceRemoter_Stop_Name = 1464532203; var kMirrorServiceRemoter_SendMessageToSink_Name = 194428780; var kMirrorServiceRemoter_EstimateTransmissionCapacity_Name = 1899412057; function MirrorServiceRemoterPtr(handleOrPtrInfo) { this.ptr = new bindings.InterfacePtrController(MirrorServiceRemoter, handleOrPtrInfo); } function MirrorServiceRemoterAssociatedPtr(associatedInterfacePtrInfo) { this.ptr = new associatedBindings.AssociatedInterfacePtrController( MirrorServiceRemoter, associatedInterfacePtrInfo); } MirrorServiceRemoterAssociatedPtr.prototype = Object.create(MirrorServiceRemoterPtr.prototype); MirrorServiceRemoterAssociatedPtr.prototype.constructor = MirrorServiceRemoterAssociatedPtr; function MirrorServiceRemoterProxy(receiver) { this.receiver_ = receiver; } MirrorServiceRemoterPtr.prototype.start = function() { return MirrorServiceRemoterProxy.prototype.start .apply(this.ptr.getProxy(), arguments); }; MirrorServiceRemoterProxy.prototype.start = function() { var params = new MirrorServiceRemoter_Start_Params(); var builder = new codec.MessageV0Builder( kMirrorServiceRemoter_Start_Name, codec.align(MirrorServiceRemoter_Start_Params.encodedSize)); builder.encodeStruct(MirrorServiceRemoter_Start_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; MirrorServiceRemoterPtr.prototype.startDataStreams = function() { return MirrorServiceRemoterProxy.prototype.startDataStreams .apply(this.ptr.getProxy(), arguments); }; MirrorServiceRemoterProxy.prototype.startDataStreams = function(hasAudio, hasVideo) { var params = new MirrorServiceRemoter_StartDataStreams_Params(); params.hasAudio = hasAudio; params.hasVideo = hasVideo; return new Promise(function(resolve, reject) { var builder = new codec.MessageV1Builder( kMirrorServiceRemoter_StartDataStreams_Name, codec.align(MirrorServiceRemoter_StartDataStreams_Params.encodedSize), codec.kMessageExpectsResponse, 0); builder.encodeStruct(MirrorServiceRemoter_StartDataStreams_Params, params); var message = builder.finish(); this.receiver_.acceptAndExpectResponse(message).then(function(message) { var reader = new codec.MessageReader(message); var responseParams = reader.decodeStruct(MirrorServiceRemoter_StartDataStreams_ResponseParams); resolve(responseParams); }).catch(function(result) { reject(Error("Connection error: " + result)); }); }.bind(this)); }; MirrorServiceRemoterPtr.prototype.stop = function() { return MirrorServiceRemoterProxy.prototype.stop .apply(this.ptr.getProxy(), arguments); }; MirrorServiceRemoterProxy.prototype.stop = function(reason) { var params = new MirrorServiceRemoter_Stop_Params(); params.reason = reason; var builder = new codec.MessageV0Builder( kMirrorServiceRemoter_Stop_Name, codec.align(MirrorServiceRemoter_Stop_Params.encodedSize)); builder.encodeStruct(MirrorServiceRemoter_Stop_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; MirrorServiceRemoterPtr.prototype.sendMessageToSink = function() { return MirrorServiceRemoterProxy.prototype.sendMessageToSink .apply(this.ptr.getProxy(), arguments); }; MirrorServiceRemoterProxy.prototype.sendMessageToSink = function(message) { var params = new MirrorServiceRemoter_SendMessageToSink_Params(); params.message = message; var builder = new codec.MessageV0Builder( kMirrorServiceRemoter_SendMessageToSink_Name, codec.align(MirrorServiceRemoter_SendMessageToSink_Params.encodedSize)); builder.encodeStruct(MirrorServiceRemoter_SendMessageToSink_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; MirrorServiceRemoterPtr.prototype.estimateTransmissionCapacity = function() { return MirrorServiceRemoterProxy.prototype.estimateTransmissionCapacity .apply(this.ptr.getProxy(), arguments); }; MirrorServiceRemoterProxy.prototype.estimateTransmissionCapacity = function() { var params = new MirrorServiceRemoter_EstimateTransmissionCapacity_Params(); return new Promise(function(resolve, reject) { var builder = new codec.MessageV1Builder( kMirrorServiceRemoter_EstimateTransmissionCapacity_Name, codec.align(MirrorServiceRemoter_EstimateTransmissionCapacity_Params.encodedSize), codec.kMessageExpectsResponse, 0); builder.encodeStruct(MirrorServiceRemoter_EstimateTransmissionCapacity_Params, params); var message = builder.finish(); this.receiver_.acceptAndExpectResponse(message).then(function(message) { var reader = new codec.MessageReader(message); var responseParams = reader.decodeStruct(MirrorServiceRemoter_EstimateTransmissionCapacity_ResponseParams); resolve(responseParams); }).catch(function(result) { reject(Error("Connection error: " + result)); }); }.bind(this)); }; function MirrorServiceRemoterStub(delegate) { this.delegate_ = delegate; } MirrorServiceRemoterStub.prototype.start = function() { return this.delegate_ && this.delegate_.start && this.delegate_.start(); } MirrorServiceRemoterStub.prototype.startDataStreams = function(hasAudio, hasVideo) { return this.delegate_ && this.delegate_.startDataStreams && this.delegate_.startDataStreams(hasAudio, hasVideo); } MirrorServiceRemoterStub.prototype.stop = function(reason) { return this.delegate_ && this.delegate_.stop && this.delegate_.stop(reason); } MirrorServiceRemoterStub.prototype.sendMessageToSink = function(message) { return this.delegate_ && this.delegate_.sendMessageToSink && this.delegate_.sendMessageToSink(message); } MirrorServiceRemoterStub.prototype.estimateTransmissionCapacity = function() { return this.delegate_ && this.delegate_.estimateTransmissionCapacity && this.delegate_.estimateTransmissionCapacity(); } MirrorServiceRemoterStub.prototype.accept = function(message) { var reader = new codec.MessageReader(message); switch (reader.messageName) { case kMirrorServiceRemoter_Start_Name: var params = reader.decodeStruct(MirrorServiceRemoter_Start_Params); this.start(); return true; case kMirrorServiceRemoter_Stop_Name: var params = reader.decodeStruct(MirrorServiceRemoter_Stop_Params); this.stop(params.reason); return true; case kMirrorServiceRemoter_SendMessageToSink_Name: var params = reader.decodeStruct(MirrorServiceRemoter_SendMessageToSink_Params); this.sendMessageToSink(params.message); return true; default: return false; } }; MirrorServiceRemoterStub.prototype.acceptWithResponder = function(message, responder) { var reader = new codec.MessageReader(message); switch (reader.messageName) { case kMirrorServiceRemoter_StartDataStreams_Name: var params = reader.decodeStruct(MirrorServiceRemoter_StartDataStreams_Params); this.startDataStreams(params.hasAudio, params.hasVideo).then(function(response) { var responseParams = new MirrorServiceRemoter_StartDataStreams_ResponseParams(); responseParams.audioStreamId = response.audioStreamId; responseParams.videoStreamId = response.videoStreamId; var builder = new codec.MessageV1Builder( kMirrorServiceRemoter_StartDataStreams_Name, codec.align(MirrorServiceRemoter_StartDataStreams_ResponseParams.encodedSize), codec.kMessageIsResponse, reader.requestID); builder.encodeStruct(MirrorServiceRemoter_StartDataStreams_ResponseParams, responseParams); var message = builder.finish(); responder.accept(message); }); return true; case kMirrorServiceRemoter_EstimateTransmissionCapacity_Name: var params = reader.decodeStruct(MirrorServiceRemoter_EstimateTransmissionCapacity_Params); this.estimateTransmissionCapacity().then(function(response) { var responseParams = new MirrorServiceRemoter_EstimateTransmissionCapacity_ResponseParams(); responseParams.rate = response.rate; var builder = new codec.MessageV1Builder( kMirrorServiceRemoter_EstimateTransmissionCapacity_Name, codec.align(MirrorServiceRemoter_EstimateTransmissionCapacity_ResponseParams.encodedSize), codec.kMessageIsResponse, reader.requestID); builder.encodeStruct(MirrorServiceRemoter_EstimateTransmissionCapacity_ResponseParams, responseParams); var message = builder.finish(); responder.accept(message); }); return true; default: return false; } }; function validateMirrorServiceRemoterRequest(messageValidator) { var message = messageValidator.message; var paramsClass = null; switch (message.getName()) { case kMirrorServiceRemoter_Start_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = MirrorServiceRemoter_Start_Params; break; case kMirrorServiceRemoter_StartDataStreams_Name: if (message.expectsResponse()) paramsClass = MirrorServiceRemoter_StartDataStreams_Params; break; case kMirrorServiceRemoter_Stop_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = MirrorServiceRemoter_Stop_Params; break; case kMirrorServiceRemoter_SendMessageToSink_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = MirrorServiceRemoter_SendMessageToSink_Params; break; case kMirrorServiceRemoter_EstimateTransmissionCapacity_Name: if (message.expectsResponse()) paramsClass = MirrorServiceRemoter_EstimateTransmissionCapacity_Params; break; } if (paramsClass === null) return validator.validationError.NONE; return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes()); } function validateMirrorServiceRemoterResponse(messageValidator) { var message = messageValidator.message; var paramsClass = null; switch (message.getName()) { case kMirrorServiceRemoter_StartDataStreams_Name: if (message.isResponse()) paramsClass = MirrorServiceRemoter_StartDataStreams_ResponseParams; break; case kMirrorServiceRemoter_EstimateTransmissionCapacity_Name: if (message.isResponse()) paramsClass = MirrorServiceRemoter_EstimateTransmissionCapacity_ResponseParams; break; } if (paramsClass === null) return validator.validationError.NONE; return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes()); } var MirrorServiceRemoter = { name: 'media::mojom::MirrorServiceRemoter', kVersion: 0, ptrClass: MirrorServiceRemoterPtr, proxyClass: MirrorServiceRemoterProxy, stubClass: MirrorServiceRemoterStub, validateRequest: validateMirrorServiceRemoterRequest, validateResponse: validateMirrorServiceRemoterResponse, }; MirrorServiceRemoterStub.prototype.validator = validateMirrorServiceRemoterRequest; MirrorServiceRemoterProxy.prototype.validator = validateMirrorServiceRemoterResponse; var kMirrorServiceRemotingSource_OnSinkAvailable_Name = 1416126401; var kMirrorServiceRemotingSource_OnMessageFromSink_Name = 1251426154; var kMirrorServiceRemotingSource_OnStopped_Name = 1997335544; var kMirrorServiceRemotingSource_OnError_Name = 1191234650; function MirrorServiceRemotingSourcePtr(handleOrPtrInfo) { this.ptr = new bindings.InterfacePtrController(MirrorServiceRemotingSource, handleOrPtrInfo); } function MirrorServiceRemotingSourceAssociatedPtr(associatedInterfacePtrInfo) { this.ptr = new associatedBindings.AssociatedInterfacePtrController( MirrorServiceRemotingSource, associatedInterfacePtrInfo); } MirrorServiceRemotingSourceAssociatedPtr.prototype = Object.create(MirrorServiceRemotingSourcePtr.prototype); MirrorServiceRemotingSourceAssociatedPtr.prototype.constructor = MirrorServiceRemotingSourceAssociatedPtr; function MirrorServiceRemotingSourceProxy(receiver) { this.receiver_ = receiver; } MirrorServiceRemotingSourcePtr.prototype.onSinkAvailable = function() { return MirrorServiceRemotingSourceProxy.prototype.onSinkAvailable .apply(this.ptr.getProxy(), arguments); }; MirrorServiceRemotingSourceProxy.prototype.onSinkAvailable = function(metadata) { var params = new MirrorServiceRemotingSource_OnSinkAvailable_Params(); params.metadata = metadata; var builder = new codec.MessageV0Builder( kMirrorServiceRemotingSource_OnSinkAvailable_Name, codec.align(MirrorServiceRemotingSource_OnSinkAvailable_Params.encodedSize)); builder.encodeStruct(MirrorServiceRemotingSource_OnSinkAvailable_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; MirrorServiceRemotingSourcePtr.prototype.onMessageFromSink = function() { return MirrorServiceRemotingSourceProxy.prototype.onMessageFromSink .apply(this.ptr.getProxy(), arguments); }; MirrorServiceRemotingSourceProxy.prototype.onMessageFromSink = function(message) { var params = new MirrorServiceRemotingSource_OnMessageFromSink_Params(); params.message = message; var builder = new codec.MessageV0Builder( kMirrorServiceRemotingSource_OnMessageFromSink_Name, codec.align(MirrorServiceRemotingSource_OnMessageFromSink_Params.encodedSize)); builder.encodeStruct(MirrorServiceRemotingSource_OnMessageFromSink_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; MirrorServiceRemotingSourcePtr.prototype.onStopped = function() { return MirrorServiceRemotingSourceProxy.prototype.onStopped .apply(this.ptr.getProxy(), arguments); }; MirrorServiceRemotingSourceProxy.prototype.onStopped = function(reason) { var params = new MirrorServiceRemotingSource_OnStopped_Params(); params.reason = reason; var builder = new codec.MessageV0Builder( kMirrorServiceRemotingSource_OnStopped_Name, codec.align(MirrorServiceRemotingSource_OnStopped_Params.encodedSize)); builder.encodeStruct(MirrorServiceRemotingSource_OnStopped_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; MirrorServiceRemotingSourcePtr.prototype.onError = function() { return MirrorServiceRemotingSourceProxy.prototype.onError .apply(this.ptr.getProxy(), arguments); }; MirrorServiceRemotingSourceProxy.prototype.onError = function() { var params = new MirrorServiceRemotingSource_OnError_Params(); var builder = new codec.MessageV0Builder( kMirrorServiceRemotingSource_OnError_Name, codec.align(MirrorServiceRemotingSource_OnError_Params.encodedSize)); builder.encodeStruct(MirrorServiceRemotingSource_OnError_Params, params); var message = builder.finish(); this.receiver_.accept(message); }; function MirrorServiceRemotingSourceStub(delegate) { this.delegate_ = delegate; } MirrorServiceRemotingSourceStub.prototype.onSinkAvailable = function(metadata) { return this.delegate_ && this.delegate_.onSinkAvailable && this.delegate_.onSinkAvailable(metadata); } MirrorServiceRemotingSourceStub.prototype.onMessageFromSink = function(message) { return this.delegate_ && this.delegate_.onMessageFromSink && this.delegate_.onMessageFromSink(message); } MirrorServiceRemotingSourceStub.prototype.onStopped = function(reason) { return this.delegate_ && this.delegate_.onStopped && this.delegate_.onStopped(reason); } MirrorServiceRemotingSourceStub.prototype.onError = function() { return this.delegate_ && this.delegate_.onError && this.delegate_.onError(); } MirrorServiceRemotingSourceStub.prototype.accept = function(message) { var reader = new codec.MessageReader(message); switch (reader.messageName) { case kMirrorServiceRemotingSource_OnSinkAvailable_Name: var params = reader.decodeStruct(MirrorServiceRemotingSource_OnSinkAvailable_Params); this.onSinkAvailable(params.metadata); return true; case kMirrorServiceRemotingSource_OnMessageFromSink_Name: var params = reader.decodeStruct(MirrorServiceRemotingSource_OnMessageFromSink_Params); this.onMessageFromSink(params.message); return true; case kMirrorServiceRemotingSource_OnStopped_Name: var params = reader.decodeStruct(MirrorServiceRemotingSource_OnStopped_Params); this.onStopped(params.reason); return true; case kMirrorServiceRemotingSource_OnError_Name: var params = reader.decodeStruct(MirrorServiceRemotingSource_OnError_Params); this.onError(); return true; default: return false; } }; MirrorServiceRemotingSourceStub.prototype.acceptWithResponder = function(message, responder) { var reader = new codec.MessageReader(message); switch (reader.messageName) { default: return false; } }; function validateMirrorServiceRemotingSourceRequest(messageValidator) { var message = messageValidator.message; var paramsClass = null; switch (message.getName()) { case kMirrorServiceRemotingSource_OnSinkAvailable_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = MirrorServiceRemotingSource_OnSinkAvailable_Params; break; case kMirrorServiceRemotingSource_OnMessageFromSink_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = MirrorServiceRemotingSource_OnMessageFromSink_Params; break; case kMirrorServiceRemotingSource_OnStopped_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = MirrorServiceRemotingSource_OnStopped_Params; break; case kMirrorServiceRemotingSource_OnError_Name: if (!message.expectsResponse() && !message.isResponse()) paramsClass = MirrorServiceRemotingSource_OnError_Params; break; } if (paramsClass === null) return validator.validationError.NONE; return paramsClass.validate(messageValidator, messageValidator.message.getHeaderNumBytes()); } function validateMirrorServiceRemotingSourceResponse(messageValidator) { return validator.validationError.NONE; } var MirrorServiceRemotingSource = { name: 'media::mojom::MirrorServiceRemotingSource', kVersion: 0, ptrClass: MirrorServiceRemotingSourcePtr, proxyClass: MirrorServiceRemotingSourceProxy, stubClass: MirrorServiceRemotingSourceStub, validateRequest: validateMirrorServiceRemotingSourceRequest, validateResponse: null, }; MirrorServiceRemotingSourceStub.prototype.validator = validateMirrorServiceRemotingSourceRequest; MirrorServiceRemotingSourceProxy.prototype.validator = null; exports.MirrorServiceRemoter = MirrorServiceRemoter; exports.MirrorServiceRemoterPtr = MirrorServiceRemoterPtr; exports.MirrorServiceRemoterAssociatedPtr = MirrorServiceRemoterAssociatedPtr; exports.MirrorServiceRemotingSource = MirrorServiceRemotingSource; exports.MirrorServiceRemotingSourcePtr = MirrorServiceRemotingSourcePtr; exports.MirrorServiceRemotingSourceAssociatedPtr = MirrorServiceRemotingSourceAssociatedPtr; })();// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. 'use strict'; (function() { var mojomId = 'media/mojo/interfaces/remoting_common.mojom'; if (mojo.internal.isMojomLoaded(mojomId)) { console.warn('The following mojom is loaded multiple times: ' + mojomId); return; } mojo.internal.markMojomLoaded(mojomId); var bindings = mojo; var associatedBindings = mojo; var codec = mojo.internal; var validator = mojo.internal; var exports = mojo.internal.exposeNamespace('media.mojom'); var RemotingStopReason = {}; RemotingStopReason.ROUTE_TERMINATED = 0; RemotingStopReason.LOCAL_PLAYBACK = RemotingStopReason.ROUTE_TERMINATED + 1; RemotingStopReason.SOURCE_GONE = RemotingStopReason.LOCAL_PLAYBACK + 1; RemotingStopReason.MESSAGE_SEND_FAILED = RemotingStopReason.SOURCE_GONE + 1; RemotingStopReason.DATA_SEND_FAILED = RemotingStopReason.MESSAGE_SEND_FAILED + 1; RemotingStopReason.UNEXPECTED_FAILURE = RemotingStopReason.DATA_SEND_FAILED + 1; RemotingStopReason.SERVICE_GONE = RemotingStopReason.UNEXPECTED_FAILURE + 1; RemotingStopReason.USER_DISABLED = RemotingStopReason.SERVICE_GONE + 1; RemotingStopReason.isKnownEnumValue = function(value) { switch (value) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: return true; } return false; }; RemotingStopReason.validate = function(enumValue) { var isExtensible = false; if (isExtensible || this.isKnownEnumValue(enumValue)) return validator.validationError.NONE; return validator.validationError.UNKNOWN_ENUM_VALUE; }; var RemotingStartFailReason = {}; RemotingStartFailReason.CANNOT_START_MULTIPLE = 0; RemotingStartFailReason.ROUTE_TERMINATED = RemotingStartFailReason.CANNOT_START_MULTIPLE + 1; RemotingStartFailReason.SERVICE_NOT_CONNECTED = RemotingStartFailReason.ROUTE_TERMINATED + 1; RemotingStartFailReason.isKnownEnumValue = function(value) { switch (value) { case 0: case 1: case 2: return true; } return false; }; RemotingStartFailReason.validate = function(enumValue) { var isExtensible = false; if (isExtensible || this.isKnownEnumValue(enumValue)) return validator.validationError.NONE; return validator.validationError.UNKNOWN_ENUM_VALUE; }; var RemotingSinkFeature = {}; RemotingSinkFeature.RENDERING = 0; RemotingSinkFeature.CONTENT_DECRYPTION = RemotingSinkFeature.RENDERING + 1; RemotingSinkFeature.isKnownEnumValue = function(value) { switch (value) { case 0: case 1: return true; } return false; }; RemotingSinkFeature.validate = function(enumValue) { var isExtensible = false; if (isExtensible || this.isKnownEnumValue(enumValue)) return validator.validationError.NONE; return validator.validationError.UNKNOWN_ENUM_VALUE; }; var RemotingSinkAudioCapability = {}; RemotingSinkAudioCapability.CODEC_BASELINE_SET = 0; RemotingSinkAudioCapability.CODEC_AAC = RemotingSinkAudioCapability.CODEC_BASELINE_SET + 1; RemotingSinkAudioCapability.CODEC_OPUS = RemotingSinkAudioCapability.CODEC_AAC + 1; RemotingSinkAudioCapability.isKnownEnumValue = function(value) { switch (value) { case 0: case 1: case 2: return true; } return false; }; RemotingSinkAudioCapability.validate = function(enumValue) { var isExtensible = false; if (isExtensible || this.isKnownEnumValue(enumValue)) return validator.validationError.NONE; return validator.validationError.UNKNOWN_ENUM_VALUE; }; var RemotingSinkVideoCapability = {}; RemotingSinkVideoCapability.SUPPORT_4K = 0; RemotingSinkVideoCapability.CODEC_BASELINE_SET = RemotingSinkVideoCapability.SUPPORT_4K + 1; RemotingSinkVideoCapability.CODEC_H264 = RemotingSinkVideoCapability.CODEC_BASELINE_SET + 1; RemotingSinkVideoCapability.CODEC_VP8 = RemotingSinkVideoCapability.CODEC_H264 + 1; RemotingSinkVideoCapability.CODEC_VP9 = RemotingSinkVideoCapability.CODEC_VP8 + 1; RemotingSinkVideoCapability.CODEC_HEVC = RemotingSinkVideoCapability.CODEC_VP9 + 1; RemotingSinkVideoCapability.isKnownEnumValue = function(value) { switch (value) { case 0: case 1: case 2: case 3: case 4: case 5: return true; } return false; }; RemotingSinkVideoCapability.validate = function(enumValue) { var isExtensible = false; if (isExtensible || this.isKnownEnumValue(enumValue)) return validator.validationError.NONE; return validator.validationError.UNKNOWN_ENUM_VALUE; }; function RemotingSinkMetadata(values) { this.initDefaults_(); this.initFields_(values); } RemotingSinkMetadata.prototype.initDefaults_ = function() { this.features = null; this.audioCapabilities = null; this.videoCapabilities = null; this.friendlyName = null; }; RemotingSinkMetadata.prototype.initFields_ = function(fields) { for(var field in fields) { if (this.hasOwnProperty(field)) this[field] = fields[field]; } }; RemotingSinkMetadata.validate = function(messageValidator, offset) { var err; err = messageValidator.validateStructHeader(offset, codec.kStructHeaderSize); if (err !== validator.validationError.NONE) return err; var kVersionSizes = [ {version: 0, numBytes: 40} ]; err = messageValidator.validateStructVersion(offset, kVersionSizes); if (err !== validator.validationError.NONE) return err; // validate RemotingSinkMetadata.features err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 0, 4, new codec.Enum(RemotingSinkFeature), false, [0], 0); if (err !== validator.validationError.NONE) return err; // validate RemotingSinkMetadata.audioCapabilities err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 8, 4, new codec.Enum(RemotingSinkAudioCapability), false, [0], 0); if (err !== validator.validationError.NONE) return err; // validate RemotingSinkMetadata.videoCapabilities err = messageValidator.validateArrayPointer(offset + codec.kStructHeaderSize + 16, 4, new codec.Enum(RemotingSinkVideoCapability), false, [0], 0); if (err !== validator.validationError.NONE) return err; // validate RemotingSinkMetadata.friendlyName err = messageValidator.validateStringPointer(offset + codec.kStructHeaderSize + 24, false) if (err !== validator.validationError.NONE) return err; return validator.validationError.NONE; }; RemotingSinkMetadata.encodedSize = codec.kStructHeaderSize + 32; RemotingSinkMetadata.decode = function(decoder) { var packed; var val = new RemotingSinkMetadata(); var numberOfBytes = decoder.readUint32(); var version = decoder.readUint32(); val.features = decoder.decodeArrayPointer(new codec.Enum(RemotingSinkFeature)); val.audioCapabilities = decoder.decodeArrayPointer(new codec.Enum(RemotingSinkAudioCapability)); val.videoCapabilities = decoder.decodeArrayPointer(new codec.Enum(RemotingSinkVideoCapability)); val.friendlyName = decoder.decodeStruct(codec.String); return val; }; RemotingSinkMetadata.encode = function(encoder, val) { var packed; encoder.writeUint32(RemotingSinkMetadata.encodedSize); encoder.writeUint32(0); encoder.encodeArrayPointer(new codec.Enum(RemotingSinkFeature), val.features); encoder.encodeArrayPointer(new codec.Enum(RemotingSinkAudioCapability), val.audioCapabilities); encoder.encodeArrayPointer(new codec.Enum(RemotingSinkVideoCapability), val.videoCapabilities); encoder.encodeStruct(codec.String, val.friendlyName); }; exports.RemotingStopReason = RemotingStopReason; exports.RemotingStartFailReason = RemotingStartFailReason; exports.RemotingSinkFeature = RemotingSinkFeature; exports.RemotingSinkAudioCapability = RemotingSinkAudioCapability; exports.RemotingSinkVideoCapability = RemotingSinkVideoCapability; exports.RemotingSinkMetadata = RemotingSinkMetadata; })();PNG  IHDR**o`IDATx^1 C n.3(A$ހC;ߎDŽ,`N3QlyJ Ag uJ!C7'*膟.Ms *IENDB`PNG  IHDRJAuIDATx^Qj1@Q! ## K($y ,;ltYvBzO(#DQ6&}ɝE'̲ ,9VF|۲&ï&~! jY͑aRoFZ7'!fg7m>w%Za--4ȿޤI]IENDB`PNG  IHDR ?OsRGBIDATH VN@vmv )P;@qU"U굗K%$ޡ}@_^9Jr M I0qclf%fQ…wwfovu7I|J1V圯JZ1 yUUd>*x-j)bcpPet{&G'sX2) n#̄9jI[ϛu{H+Њ.~8G|kG7c )6?ml)iL ʱ!eL5NjXyRBx$xp,KR }>QB~FJ oR7jppꝚqcu`Qo4:1&t%շVࢡ]a!EӉNHՅJ -f<ӣKx}Bu4xP`yЦLQ=FNtD. @5pGˤ_QGY_ Bb۶c={_Hu_^sIENDB`PNG  IHDR ?OsRGBIDATH VoU#m7v6nm%Ff` &^.Fȝ&zN aAV+ [x]k-x=̚uryy9|ؘrd=xR.Dޑbh4Oy+'?x$w`*!\E|#ܭ>ȥG:CfQÂX)T*-PRs꬀C }ãBP؀bITpzs\mZz|T%D$-;/Ǒ٫w1,^4=uH ܊׾ 3ci[<žVĈh&= l}ZɰZ)Gn-?M݈ 7"xۊ/>Jwqc7|7~;􈈑93A\u$ZoXO$7+=Ŗp\.E[}HmЫWA-^$A]P0Ljl:9'.ArPo8\4<@(ϡ$U btq4E6E<G9E[3 :w CC$VWW8,;Ύx<7`aad6ÿA\r>8H8 KSn4IJ1=5JtJ C!P@" HR T@P` j#)J$Vkyd|.J"zJ\\5tPh~)(Rɼ:*jXܺiT]Squ)ICZ7?9Coo/8ɀ8tuuazz "L gG0~"d$*׎qfϘ)ʽkI^0KɽSTPP%eMbM(Iғ닒QH OFu+=H M(/oBZYB'~!uH+ _B@SLҒ^O_@VA ~NM<3ҢO"?$4%(/nG*-':1_2ݷ%"d#c.i݅Gl/??hOIENDB`PNG  IHDR O}PLTEݭ ~~~///000<<|IDATx0@у1OxhA,ᗀvrd_I/[`->,h E)W5ԂalNGt64.fhAi/TjYH ͊m7$ ?rF#?nIENDB`PNG  IHDR ?OgAMA asRGB cHRMz&u0`:pQ<nIDATHc```~ ~ AvMb fXJG ># H}911Z( `up?] y4 M2yXw=IENDB`PNG  IHDR ?OIDATxŖ+ACm۶m۶mֵm۶m۶)Fj/&c<"##і7rN551hO<"$M{Vl [At?7tA ='!>r/}eD~$y Wbrl[}([9(zQD {BHZ Kag,KsMe=9 3ρ&.v"+LJX( xہDiā)<3 e`M%lbAzR( ;ov|\AHu "q-\ҹ*0jZAQ'DYI(Ʌ>x=D5l \(R@Ā L}n=˨ q8H-JJ`mF2T#2 ;# Pː?\y$'Y [#;Y܏FKI 9E917;ޔW*>b5ujǯz}3Cx e8#`e`+ +-CW@wv2$=p:TP"jB+Ta3*;pd=D|)>eZ}Ea ,[g;&vݐmQ{mv?W,v{IENDB`PNG  IHDR ?OsRGBIDATH VMhAf46iCIBEJx(*)z(XA<(ARQ䱧H~C fQF-ka*@ rO'a,$øv CNM_@Rts0X#M?B^r9mȲ]֛6]T*R&pZV!raqqP`P8* ŢCLLL`mm nNSS(ߏl6A #L"ЎV:$) ? {QyIF8~GIENDB`PNG  IHDR ?OsRGBIDATH VKLAf)-X(5UC1(zĄ& 111Aԃgx3QP Q>e+R.ufp6,G9w%в:pB$uUU@ PxJd2躞K v0Tm;mpJrq)GlZJ\ "o0g̡LOLY<+A$7珜 Vo"X@L)G{$~/g>Ϗ8(no_ys\žP ?9PR۽(:[Bvl30x<+mNvR =U7 JdoYvp֙RP-cB& e^9B>KF3?{=wy ! wW\:h}=x< =3<{[υNG!8i/<2o-/=w[ KG{1:3“l fRCUqI.t4Gχ[aHDJMɎX~I}F/mUE*y|W3ѲuSEQzmk9mJlt&ɮNlC֮w禍4o4'BEX!(NXoX \Af"%쇄aK>*?NO9IENDB`PNG  IHDR ?OsRGBIDATH VILSQ=sԒbQZR 4`b4J1.tebbiaqƍn!jbC  (BjKww{~O*D%;`&ZVBx< <4R0uٿ8GبҮ}Lx#ѥՠCPA"I3-O Q_˟}Ƣ|=O?Ӂȋm K30 Xm%mH-4e@g/4z&~x25uh3EF < 2e!۽RW56ҢސDM)"8R[ F+ DRbs%+>(k툼vZD#|!UXf6Ӱ㪳BIaaqi W;"@`;xrye9)|o4bC>B{r <5>oéG0tr6ˢ= E_ /h2.ԗ[pMb*| ?>*ӭ0 b2|%dMuu G:?Dvoͫʱoa7Cm8Z_w` hw{F#˅qh ؞p@ atrցKJP[QRFl'8t {PSϾ~Md?mw7׻m)Z) QYh@X Ъde32ƏDLy 4!n_E;±^IQr qpU)Aπl"ݟm0D^.`tNDؔ~ed{@)6C"arl'Z!BZTaS^֑wqkc az,K:傄L B9)>$s:M\ LeQVQIENDB`PNG  IHDR ?OsRGB(IDATH V[HQmLﭦ^*̜DE䍲H!@4!"%ҢnBr9&I)ޯrs-'&=D"lll"`E2Z[[e<oj*Jf*zrR))tmղHGwuZuf>lpcrPT!3yfݨ( G.@R|rzWbS!WUԾ$72fv'ޕ}<:=J^ɩShQ>J/Jʑ`pXC;DH*Dl/Փ%N5Ԛ z6vF Q$lw+4w` n9R{6}mVsC;Vxҳя9ف&UI5 ~$0(@|l l96h`dۯkՑV'ʟI-^iMz (B?~R@;hlF;Azp3ձX,dvvu ̞\sF{_D1H!Q=\p!cF4J_w{pۘ ҝR*ṪRΎŶqC[[,v`>\cnfkqͬa yXHNCELx?r*4$IENDB`PNG  IHDR&VsRGBPLTEUU@UU@``MffU@7[mmmDDkkkffs=Uamm`jjGhhq ddmajjffoHddlF6biiI:ccjbiiddjGeekchh`flddi`ejchh_di8Safk`di aej`dlD8Cbfj6UadhbeiD87TbfjE75UBaehadk6Ubek`djD `eh_dj6c6T_diacj6Sadh4S_dhacj)`eiC6C_dh`ei`dh`dhB6aei`dj_ciadh`di_ei`djaehh'`di4T_ehDB6C_diC6`cjB`ci_dh_dh`dhC6`diC6B6_ci`di`diB6`dh_diC5B`di_ci_ch`diC5_di`dh4S5SP0`ci`ch`ci_dhո5T_dh_dhB`dh_di`ci_dh_ciC65T_di@`ch_di_ci`dhB6?`diC`dhB5_di4T`di4]_ch4SB_chd@B5s3\;tRNS  !!"#$&')++,-.0137788:?@@AABBDDFFFHILOQQRZZbcddfghiknqqrrssw}K|IDAT;a/:HRrLّMDB}GXʱĦCt8*M6%{X^sMQ>$j^ݔÅqLF`UpF+y*Fuȃk-#z*ۙan6n_3 / j_$؁!A˔Vx>$OAg{M~悄˒+0, dزEl-UXz-c &kZe%ċ]*d8#mTufzKk#mYhpek4ǽ7IENDB`PNG  IHDR ?OIDATx^!@E9"h.q4` 8 yi`+ ٬Se_E!iF]ם*jQijCplc՘皣HOu0wq f_C]$RQ|eğ ce!SeyI=0Mč8c a {S`l?Hn$М?fuQVqXIENDB`PNG  IHDR ?OIDATx^= P=x,<JmE ! I AߊVY=A CmQm+J)ox/{湌a(OϓmÜ3_/PUDZ\Bs:([-i['qDwi߁-p]m Q$ _ xGH(Hcg?KqIENDB`PNG  IHDR PLTED??D?@UF@πC@@?@@UU@???@@@?NfG?@?F?I?@@I@MB?CB@AD?@E@@G@?@A@@?????B?@??@?CI@?@A@@AA?K?????A@@@B??@E?C@?CBBFAFA?D@@??A@@A@@A@A?@@DA@@@A@@@??@A?@CA@@?@A@@A?@@?@@@?@C@@A?@@ADA@?B?@@@?@A@?@@C?B@@@?@@@?A?A@C@?@@?A@BBC@@@BAA@A?A??@@@@?AA@@B?AA@@@A?тtRNS   $  BЎ"%VU#&]'wvRґ}`=ǡA:6!Sn-kdY^P0G3Jی)C(HO4Tuxbt.;<_j+ha9W~gL/1NeM٣{irc*I\o[,pĶmZ5ܽs>QE F7?y8@f2KL)e8IDATx^g{Tuo3dRN$z/&wDzMH΢X@A{Yuuյ};3sN33;$'/%%%%%%%r?<{=P'bXq/ʀVi`]kiؠoke`6k曙H>e3HKEm$S_tnH#iVKӛҥf'|H4);$Yfny9!$.R>46R UF 1n,fDf$ؖZ ?(9֗auHMi>6~ð@4 ][0shXmvwT/b\H:"œuŗUTS[h-JoDm>L{+dM>RЂMTLDؿg*c>"S݈uSa0ß"l_/MSm96v0ѽ%VeSZ̦جj9ҭS [Ӥ3F>ᮿQTKoS`8೻k?B5?^dĈu0)yc# ½I7"Mhlm4-epmXk=<4)wJk'Qt[(0{mwSUCS<JtSY j*İ6Zoz,/FCLŴ;(wQ>MڟEč8:6 Dp<ςswRLiCqDQf)\KΏP|[ t /sE\xE7ـer vbAG)^ (b7 #fV[/\Hq̔zPA32S4 Mn:B!Ϩ>zbܙE.DIծbU z{ ;cqXV#SeyP/Q !·` "ҾA[T0,ז Dd#~YZӾR_K]ZBHr}j AzdzXTkK nkYc@LCPm!pRZD5S}`@5-> CMitB]S ׽(!.(ф}0dFPjњh$SQpϺ+4Lͦ5OUMn6&*#p-az"J "!ʩKnIgn.@D=$$&Z:^GڨieVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3 cHRMz%u0`:o_F IDATx}p?{w!1oT*KEq/3Ȩ $Z$VLk`ǚdDZ3jLL9lRA*5$@r~Oݻ\>>s|}~wapq17MHurr  tx/ρv@"mѭnd:UbJ` hz.ra3e DR_;YnY{֝>@rpJ]bdKw$8y /Km%*wVHН9y"ֹ` vUsƑp|x ٯP( ެˀ;.s1D}Wu#ܿﮇұBiZ2uۂz mPs'N**d!i: m P$x*]Zpu[wֳfR8y2{5 p0|&aBцHdдPؤQHhE9sVQ`Ņ@VAMBO0ҫYw/lgCOoWIM$0jg!\;  YO냞[h!683&Y6yj1hUJ2RNH?ߥYv q뭯6 x})j98 SPP? < _KǙh-yGml 4圚娨g8MH9KTUO)õ.4zguh(,V(? ˅ù;V1A~XN\VkNcKހ oSTDPL|X)R-㽒"jR6H|LJ#/ٶ_q&u  .:%TCrDz|x&؛ RlޯHmĔ@P.{k/56oJբfZ-"6eU8(~% TK]-6e6||"6y"\+# | fo2<K@a.̟fGW_`ZQL% ɵB|鋇SL>O 1LLK!%O%m2R^4w Q+$R**́ģUzzB7t( j9}lXQ+]pӰ\W w@V8%d- {*wڪKGՊ-RDBNe !c(ӿ5a4(J䨍Uh.X!*ФND Y(`Dn_ 9 yS!4wC!5ݳɒd0-B RY&ezlRԨ-E$s"yb UHTIu_rvCUr)7N.}z.-kѱ39wB-<8 ;3B/Ziti[6دvz8o"Jr yJOl2SI u }TiCqe`(uk`yAݛG'W;xjF*S2Z;S$+LRNQ]Ee P-UH(֧3*QO#&3Κ e}-]Vn^˻ qs۫oH % ֭dN1ekŊ~iTu|4hiW0A qD01wo-%C݇x僵l88dj.e,$5#q򩡫r {[@:4I!R uVF=hs惑&%:b߁p8rȚ Q1OIhț ,ў:zxs}h?9?AMҁ3?E),4*BU:_m1W1u )+e̒ŔT x"a54JF{]yi{\ۻ}04 AܠB[&SnaJw:_˙Awu?EZ&0yM),HMg.V,N|CԷb@C$ir'YdEp:n&x5/{bεK clHUǀUސ6d׭[2g=}=b2]5jՅKl`i~Ôha׀Vǀnwd6'3=OchX>xo6T7j].Y+Xz<>?KiaK+Ϊ8p;p*,euh>D,j:l[iep"i!OI k S3!ck˴b 4ɇ I>z l..IL7IENDB`PNG  IHDRasRGBIDAT8R=KPM^:XA:A'tPMDupqrntsI~uUZ:sӼBzq LZ1 hSz!9G677Q %<JHH(  }w'tHC9#w%D8~ndyy駟޾u&G}/tm\>-6o޼y>YrرW^DGVO H___ .9j6M'}')rʭtxO>p8܍`mfȥhkkkk4==3H=%|rRBn^+fK~ɓ 귥Vnn䔴Y_x]U:<_ArAN/4c @ 7nؼvw}_!]bpO.\];?ŗs⦟bÑߖGҿW^^E''+(h"ܐ#r -puߑ_.--W7(q臖7~W^vR]ůwZJ~a.Rf{ِ#ϵSD, !FĊ)~䂜rDGN;__hnnn [OaU5T~tu{ Ҋ3/ K2/ C9PvH6Sh\1!6ĈX3bG9!7@_jkE1R7//ѝEU D"9ٹU5NCQ;ޣ̈́>jg73-c%@9(X1 D!VČؑrAN 9r~纳@m W?6&:hr}9ʆst^PX{t256~O calapr䊜;`@~?|h2#(Dj>U<O36*T>-4.p1G+rFTQ0”D4ߩ~2*GiuM猢˜C\3r dpJAQO!|n>U=U<9B={fS c A31K!К\3rԆF\-`bCƓፗfSM}s)J cf@!G6 ~QLex2_HVT ! oEȕ6p݌ SOύoXHn\JڭIu]^Mͯ6vO3c>#8Ďx+Bȕ`mh`ט^"?tGgSҙJWk ׊|Ʈ`Fu{@e 's;ƓZ93lݱ{<+_RccqC#ynmK]WNsٜWNzgkc*KtBj׷=LiZq@p1#v@!G䊜@=~i" oPr]G@e ^/!w9\ 9m)or R1,@NԆC7pO^1.ϵS3FDJ˥ɴJ4jW12Z)T-Vd#"6<aµz|Vէi,]}~`l9/^cw\ɨ4u[z bBlyp1ֺ & ]DeOS>B삳S7.BN0ͯj+~/ \{2@@&#@ U'x_zU~ 4 `;/g\"?f V ɠUw^':A|We pq 2B^`FL-RTxOX~ Bfd/mvOP>@@ ʷM甚"Sl b,A/Nu+ 4xJlӔF3Cs[vr[I?A 9fW&F *b_\\@M3tQVX<0'V5Z-cz;Űd y8ZaaA~ zmP75#*S&w)TBٵ.yj~}٣kRa,1tj=y6 `B<^аK@uNJ[ܺ_^HBLE`jA՗Uڌ,'-\4d>NKH3q}Efeh!Ik.\i1CM3.v l`vq7b+Ja9^e\HR~lMof 0yDBӨ`Zac"0Wa`0ATqY͑o^ם7gz&sWJLi~6uO7/Z:$~0_T333iA-x1[@Ԛ)u٧+nM)~kϦw,MB!(?F#JU fA6&g:?55%?f?I@h^h=0rrR~ `W\ 7bbB~ !p&pҀ(}drT3`0(?臿:MGP;@8!7HGOb+9\A8(VB?ѓJ8C>h[I/l g%0˜tDGJF/|d=t.4A7NM :5TA@ #XE[4V\O7' / ߗA @NIzt1qt1()1P<-RңOLM#N|મ#9<+6A  gK[*G7o>;ۇr? rzԂ* ^6V)MWJ|@8- !c_Ox46⠘hGK\ȷUx0Hn?xꩧׅ ہPb`råCdvCQ''_)Is] |,[v!!¡**5\jNCC^x{B/ /Z&;vB_@2}מ1~mkŅ\3rw ' B,STc"䊜;<O( B/c4ׅ\o#9##d  %$$P@@B.!lXIENDB`PNG  IHDR@@iq IDATx^[WW0AOqlm6k,ըQD@DxeG!(*GKjlͦ&qG{ϼ&3~x9{y~swK{ox4>xNބha}lZt7 n $ij>ÂpgpoA,8HgpЩ~gp?Hgp`AH(XLH@uhJ6E6OD#WPOLS:Dy#,đ2 22-/!a [\Jő~‹ӵɼb\>U),w)W #D},#t#pG qx|^NT+Ȅ}/@wMG^W _"ܳep o&@V5TNBSh`h0Z5Of-RԤ)6>znEX\M: Xv%o5:kG_7> )z(qJ AGLVw.Z?ô<}|>jGYWڧ!W=Yd bD/,Y+]q{vuh(X\`K,ťiQ;pDczgdbjvai6"ן=6BS"RNSc5w"O xjs]tY縧@a($HX@&ѐ=-gĶiCm^hY@(]fjPѮ!=? z )cI+Cu"_՝8'tbgSPcHBY]N47v&Y Їץ*/D]#]JڞR>ЇGq$?r*Ꜻ0Qq&n^ZyLe'q9|FqŶ{#'4jqAJX|!;#:F-4 9Z#05Qv^%EUeLBcjO\y0{GwHةDN~y6:SDv%6@uqB=JQfI2Uy '=L4{OVs5"˻> "*6ԄxPU)a%ň sx'͇4X6L EnULrRØljpx:[C"Bu2Gʬߛq^m/_\D~rfi}Li&ERErSs3 ޼ s/v_^Ez8_EM1B^\,0PY|'HĽ\W|SkiDBm}+U#8zVģݹņv4_l}2ΰ+1> Cתu|''؁LQ ҈י J}M#cpAbчT6,Χ|FK%6Au&Fl/KpTN"gn,,%jh<ސo|~i|(߮0֏]y¯ṔQ/ di/EUM7{Zaah\"Q󬊾э ѱ;Pj*\ΑC#$ D> H ehH"6>:s¿Euv2[5ɐ|uack<1Y[TGQ 2ES |@Fu|cйjOՉ*;+P+ҹ69Od_c\;Hybu ē~%%N->9n)zklm +wƨs-!q|15y֜V2 M+F: I?@^ @ B/lJ*eym«9n޶qT$55 (]V(:4%m v9zZz^#!;S"9Bu$H86bY5EЂfb:Z8g@{`3M3B!(d""FmP A#ZC 1|Zz&>k>" DD@$i5!_`@gOCR  AOk{|`/~_WfKS?v!۔&8o2^~7mQpWɄif>_[!GIENDB`PNG  IHDR&&4!%UIDATxֱ 0 A-i9+(AFH #Bsf!_ k?#e̘1cƌ3v &]*ڪ  ޮSIENDB`PNG  IHDR00 1 XIDATxر 0 A p.;BXx|EI{ܞk^ u VrG'#cH|ιIENDB`PNG  IHDR&N:IDAT(SI/CQ_ 6XX"$j5THMXAՐVU hQo,9ϳ9P DTF?e?1)CQW|~8NLI޼ːn!z89}3jؗAJvwG"lEpC.[fۊgk^K?!s K/O2OfqpEV74:D,GH}. vv!R!yDGDĊrC48H{Oh娛45b6$\n籰ےWȕȠ~  W6d;dZ FPT5ͅZXO8]gdlB4nߊ#w>Pgg;̠u[,*e;5 IENDB`PNG  IHDRr ߔIDATx^QgPw3Weo! /0|,"S~zW0a6ɾL^)3)r\B@Č_6Rz#Q8cnY{}D|zc}5 >t,5& QaLiөoHHQAT]#_T! )j2Ȱim5JW?JuO v۶BB(ETsX4Ě%D_@qoFIENDB`PNG  IHDRr ߔIDATx^Ag\Q{7!RB(a(eha4UV颺(2dJB em>5^s2ͳsN@8@ b<#( )A/0u N 7Q }5_D F|N1%bgT0TP"9piJ& XPXHgHKEY`YPհX8kG22pғmiZzAbF+<0:{Aڱ"E=ʫ8A `'cFs;segiÁ-\5=٠bCL  e[` Pq {+ +c.hJIcGu K۾<~ :{}vg_viT? M|2N}i c9:wqΎnrqg;&wp @`Wbs"<^o2Ϋ^kk."Qm__^3d H8QE씝`*1w60nQ9\r$Bљ}DjZ}PDKJF^ޥ܈Bj -5ry(Ɲ]3}SeDsu{SG/]IENDB`PNG  IHDRJ~s^IDATx^ӽKBQEXQD&H[CK4ED2Dc9CP$DmHPaAz@S(3c&K;N ЇeLxEPd7R䨑$A )NƸ&'Kq9,!3L3#!2H\ VG+Pe@dxYB l I(]v5~%}&Bo`yiN Z h4 eXS,fy#J[%ud; ąIn&W< x@b *xS|BQ YV$dxǍ6 Ff?)ڀhds(>IENDB`PNG  IHDRJ~s_IDATx^ӻKQ7LZŭ!Ab-jPCcSej(- J.'8{ پ%BG782M1 AUxHJCNq25@/a$AAP l/ifp`B}@A80=6 4D8A*bQ: jEILErX9`1C)>J3OXLVC29n@I4xK~z&kW< x@b |s(3,C̲H)ۏ3߮ q)A̩;vIQ`?iOi#IENDB`PNG  IHDR``w8IDATxShHo3ƞֶm۶m۶=l}e1o kM)RJ)RJK2\\,!Uޗ>Ϧyϟو>A#8N7sRW}NS%F%u3Q*}Iog, 9$ց/Q4r(Y0WOu]z.uɸu+] 4@4@4@zf&h&h&hLf-GWn@yu-ô_ tp2w|/૽&@fw$c=.@ &9it>5.9]qvq0c9!#Ol.f AB6e ’ 9̤^_g&,۪,Mks(tpA3f;q $P;O(u& $b D1 )11 0BpH~Ŀ_&{+5/vEg\57|H~|{|нxnE>fUAz"6|+vu --;ejѬ,W?_]ا)f.3M:VܢYo,Bda0kHk:MZ 6ur;BFz;1$-xcfgRZŠ^|؎qlyqŅx0v ^-CN0x-V,uYeb>xuX ^\0}5J,^ V[K@Z10Y#eGPMQԙ:0?^o?|*d:hX;Α+|*Is؏/'&s4吞F7 j@CB6^[r6n ҋ*XiGҒծ؃%;:iZ*vNO`cʢ0ưWDؔT2Tp|iR9:P"L 6CȌ@ 0; px}ǜoj %q )-@j>nn>no gy R; ¼>aR{"sż=sXT=KC8 OdDKWʭײD.`Eʌ(юYO\31K-=NjTϥKj򂺎܅%39MŸkʱp&PfWmK~<o-6*>'P$q|=QR)ݎA=3L"6!M2hN}~?,U実@`m/+ŝΨ b.{#5ޛcͅLh"$^45ϤF~tA4¶ NwWϲzauṡ$s^IE;CGvEPN{ kG2?8)QyqwxZڔ;E\oНPYqmPN0|W"׊r\ 8ؑr"g4;g'XrS{L3p_ֵ5\v6֥T #2<8kLgAlj*Q}w8+t{QЩ2.!u n׷wר,bEO4${`.݁nOQ@/׋_d?ex˵mr8=Nl:"~L;,#fAB>ײ^cX0S@+H +NXzNR6YYO*lL9$)I0zjQ>/> ,o0b?u;rOgz"͒0 >E&g,,x7A찬H e^ibl"ݥ¿#7cc} RJYR -sFOMg"sT azơͧAAb?]ݹnmpw{)N⾗{`taxޙuSGz{KLvGzٞj2# H! R>D*jLJYR?|<`1Wi8 ^Sfykޤx1%!Z""cl(3/?-}fI/~b^(Y)\,(ݢE_ b]'`G%;:g]fjTEZtІѳUA;/-w1E>CR,"hEeyѴ-;Ë> z+p*YuuG2}\cnQo8 =Tu;X#> vAVF퓊?"p"e2WH:ʨ7!5|.ʠ,(2a +1wl~M-/XC3=-de?'p`9;°f2l@wey6T=Nw s.TY]X5A$/[. a6+[Ȫ ?``aەYO٦x8aU k<Ea ~‘~}| k-Cd Y0Z|b! 껅c /^(aA-փЀG9*ۀvxCmteCy!{88{ПBO<)nx~P9^ͺV]B21]輨"gHxyT_:߃€]: +"޻'cN~Zґ_Y^aOB Ҷ.\8s+V 9! zUO~-< j-UO`~db.C_׋ !ui=.o#;D7r@D[(t.|!'7܂@YE!?adp G0̪[aU/랂0OzpE/q|`şeЭt>|/D_/a<ͤt !/} uY?/_/h,XGQ8>WP剶@8տoSB/]J3^g1O2*#AkWo(~!dzR|:);%tC0ySVS 6&;qƠ ¬n^Wh4h7JqJTw -gks@4 %H`Q)2;g7`K)B,Y!MY@9H)FncѢegg{§˞h˨ېACcVM րY2l\c'xo b7=*̐!!xP\M {~# :Ih't_{7׾ܽS$`sleP{lb/d [aU"BsFű#zKIrUa-_@E+U7WcIqjGa!Rz(fr؍ZJ9쾹fs ˎYpF%wpFEL]VV^w$JɥdMb5;tsUJSf;䣈ŒR* 䶿؉4D~GXcq5ΟshɄ7}:NۍYMYӻK~Al= )oJҋUz og[=C^ܙcmSzEƋ7S S[a§1( /@^ۢ1 "N^cοfq}Ne7G?d>W{W>-d^{de`!"͜R˝ I%ys(wA Ct%et-+YXdK|79Vr7t$dDf%2  o' Ǯ&=!&GՕ:1}) nv7g@#7[t)tdGwƴ-=> cdݖ9y4ZCWRԶ5o+Q/zx+C5)6@<ݙ 5GYJV攈.%eh? 8;'*|oApM[=M!}Nd+ tU* i,ڐݧ}=F`H*}gnVLJ hאٮ{H&"`|{b) _UC ~c~W[ 33 w!\~vt8 Ǯ &.9V$aĖZ&.ȽȻљ|Ux',vA݁ˇssž?Gj4HNW`aaWG;R$7ni[/1r9g-뙻˭ypOf?b-hnG/6mOj%f&K<5@Cb?gayEe:80`@Q/Uh zO)Νx1ӡ9'a+vz]2r&e 1WkqJ"6L%rқI76mۘ@'=W7߰ U P#)lYE `zEZ&߄p<:hONWNZXetipGBۇEo (kȿ}&<}0_zb/N8Jѷd'qa>Z s7a^;8m* B. &zãxsBЪ ֵnR$&lώ\4g3<޻_|5 5ֺ d&Iܽ9zȐDFU2̼z|UVͻLb/fsdf7Ym0y ]ؓ/>8`ShaF< ܱO'nlLFuL9r -})zѣMCd}@=+@ݢ>m 61c/N0uϮjjJmx ,8R։V.qʕ'RiLY2'C³u5ʑ GQa->`};=O8xҡS$# AakLw]x;9%qM<ܶНosQ %^P\7Q!Ef$+)8&wJ@j%h19$Ce<{~ &K> 8QzrDϼT~]@Vh'7l 15#'c6\,4+.2,e2EZy4qtMqs͘Հs?ҴT=2' U# 2|w;NGada݋;WvSy`PO]:T8Gc勐WfDX-*a Tg hQ$n&{є[fB$I=jSLjqxaE oA,/*QW>di =|\qldzoXl)rE:&mk)_ܔTdu?SF!=oY#8Q&!S׫?a+{DJb8eT{*)=&&"ȻIqt5vl̉Ǹu㫳u·-WR'\xN= Mxp6wmvEq!ƵAbhzPƏzCn0}J;8K V;f'@Wې^? I@yu=pxXͪU jޕY|s{8IջJP4JG>`Ә]bpt!xVa8Vedʕ%nZ+ubEyhĘbMmZ*QOw4]VU`g0$JGzND;qK򒶺]|K^ ,_}yv]bfP뽐o'<^O=[QlHH؋M{җ0lHE`Ւ܁>@ P'Vf&",Qضa͋]He CdI%'Cvq+1A#v;^AS}&Qq~ȭ]ƕ59e8o5NR#@UzG]6v0㒭q<6-T;+i+4wl-.niI:Ls"8ikު$4i#8Jco*ϳ3:4 ֹCtz.EZ@G™TIVM)ThD] R`X˻ F2tkDy:`&>Qwˀϸa|3Y 8ږg. /GhuЂ=V2[¤I5P"ѡNrXA-N#0iYV{.-N KYї6˱[zT[Lp?h|\+lq 7./ LRۄ[&>3_-0v4 ðC6yJoBwd2KFR@Ҁcw4 mߕ #2m$;ᐕ@V㐪mPbM3S2Q&{t 킕=R]> fW bQ=ASJEpTVEGv3!^R︫ב-2=zNRo Bd^Ut V>4Xk%zӴ!I xe"8%܄Իjx~*K,݌L6m`s4h񁅚F35XdZ'pY-^/W-vry߻dy]rR$y܎Bo]#=HNylA䒧!$w* Ĭ.UdW}'U7J;ɀlt%˓a;ީFv9"iu?4Hdvr~1Zy,S䈐uD3ApsYYG(o|0R+5tmDoM &CITN.^I6$w a#MVe5ĕCB do)a7>vWw}|(Gm$IBc?dX}Hj|f5AU_~?cɧ9ctB{lxIjz,ч\"oV`wP]}M?|-?ASH2-G˰2<Kb\s04#g"z}m~yO.i{IrZ7??qMS O_^ame5c"W+!Et-쏬QuÚƟg6Qmf5Լ;i\?/ND=JʟHXC 1v꡼vWmu>͙7n[p%ZuW-Ljl⇂67tae"&Cn 65'LÖ-c)Sb{R(+E@\ό04U ȉ7Qho:dޯy{L=Ȫ?U}R#jWaN9L̓rtD}VAKq`,UI^)zsDVfn`J|v'!ć:uG9T&ASTjde; K<tfIxH Hj;j#vطKJv\.gg"n3qJc*'⃑0*o& WLb3G?1<#O~<pΪN>g&mr ~)_(oX'zc4t?ħ2nlv Eо[8{ە}{-}&5?~0oj̅mp^o5Ř9_>nhD-H݂_?8MI_ű/s?5Y7^jv"g/o]OĔlR gslų-9;a~9-dCy?'ovec𬭨!BȌ^4MѶ=*5/(MbS 6#6WhP'wY/;ƛxs%tZY Qlဣxɏ^숌pl̰3Љu #NX>WP8X~9CJ1/FfXm"XR1Ձ8u& nu`Μ[l=ifW ĩ6*d+KHdX@)[onӴx{k)gblC/GEtVkiCin_;& l_JwF%~!֑a+:2%߈u:Or_%r2Y^{pI\ ^=C dB{W&M6aUؕ^N⽃īM069Q^dwx:V(elX8gHk1 d2l6ݬTJG)̭b.+ԕˍmM[ ix#AD7ĵ 7ߠXNWGi4T+PKU)nQv:EwGew`)Z >ȥpM>9% Kj[H>;+;[t碫4d5J֥<ϖ3\*wcl@nVhӏyǨZoB`ϧu u (ugwXӟ~1,~x7h؆|gsIkO]DdwP1'5&F O9:Ol= ڕp0p2'i NDWD![|,МFNںަ~뱑o~:$wZ6&c~oR6~AiAvxaPFllbYM0SRꗂkaJ/%2%uylm,n~vȩI:`En"R#E`ni~&\#][c,ƕMdK0B@)2 D0daYw\aõ.kA6ox]c(1S7t˨h._w 4=O?67є.ͷl2:v {tvzYƺ-Av:g#б!F%Qt"7qDh̩_V,Aק]QaCg1uԜ*أl,pTE=a>#˵ej$i-otB KD!dH:=_kv-^gg{))"q֢ ;FEY'rI}&.2V)"fSVGZ|Qi6N N&_cYS 82ȴ@VQ#*"e70^z跹(gм~ۡzbPUPtam)a{} `߸ RYYz`iwñ]AxV-{,!}ޞ*eo0^"Z)4rgkANr$a ?H!a1+{MU[SNF(Dnk5 ط04n7]zfVU n+k6(<2\eJE,sg ȥqcàMA2,qjDhD!VAw2n`n``8͛Lmu|('|ݹnIkK ^L nmԁ *ܘciOSy;m`vdq*If%X{OgZ3qG,WܗigLZ{Z/=Hhc$wЉu-|\ I,FwiwsG 3K"=iCxEOGoY\4B><BWM:^2nS8FjA\/iDګ^`knEv~ݯHǒՍ=S\9 ;hvЊgTJt@8L\xF]텲o)ςŭ +?3Pŵ>K=ZVЄ N(YEԽFztPBk6;5(W ܲ<|Xʦל bl%֛QFtˊRvzZw.Msn遝ﳐ%cH7"M-&INև,hVP##.o,b퐚qwOWjO/>l^:J:L6bZ#٣&)OA]+ޑ~ȥaq_g<*);k!|lSlي@J7ؾ--JC}l/<5?Z=)cˊ7w!w1:wuMJیNI~"66LqGH'7H$Ce8`!ⶓ(`^"_\7rל[tD`UN~T|T޼s{!q|vGO ;mӂqAOnĎ^ɫé,Vts"f$ cVב ׸'>qnGd/OsX%sFM'x«vF8#i6ۆvP0r& Q49%RhSΦ0Go܎ܒ{M6 mv8͍ߖ7lOTsת.NwKܓ!:A\:X#Y XR+PBpzk:Bݜ35ʛxg*CۘF_/tA?Z;;yY!%^\k=fǾ(_o=p?]x͸hy(Ejrd) "ryH8{Z3%<]̌$J͘SkI߬s#RF'[gS(pPh\+D$1:[zL#*&+_[CгJ-#kj#F\Kf9.A8ƢtP:{F)NHܭn/==2wd]˓s+̗ps54PPҒZH3inx H2vBmNtJr&6Ԁm=p\ǐ8qkC"] '|妃BBv}S&:Z. ܫptyTT:XE ZJx~ϋ8ӿiDwwsJw}>qxb p8OH6'WА~)_S* z[N#iUr~[ytNǹ돲)?uM <>E1=ަ<*Bt!_zy|Y9YrUQXY.WG>#%wE(/GW?==Cy3/!? %zt㛑,4_9c3Qp"_WltΑt(O, _.y ئ]{O -=Xd=l^,{*^1(}ŸL 8FG ȿ*e-Ơ[De/ۄaZwQ2tQ J[Vs߅9u+n9>";>][n1D3xK՛I_#op'F쫧-ȿ?Ɖֻp[˗dU3\ǟc[~ gSDFߘ~Z&979}o=H-؟[©<>TI;}>2[>GpF,]nQk@]ɼY籴l<7oI lj?!$hiGe 2V;$Aʈ>Opn3O A<$7EOVvwrbE6pkO6MݎnXf͝'!D21VeU]Kֱ10."lo&;n;Q0 9>MWyV8R%̱cAxK&KeU%DG)-fV&yo+b2&&FbB7ll>mqn Axv;7#dpb䒉UH%^.wSm{}Ԝ}at.t~$egGymN&amH|؞/wYImM]18zIR`1܀l;2⇉ ꋭ~N`8Njw#9 ]FQ)_4?싀(;_S>U%m r{UzoNS gn,Ğ-.גȭ=ce;gǤLM&؜߀! JL| nW|G#^]*YKMI__/Ku{msG~(LV$ oy塠v(i%TP`3pV*ݷ9,՗L$kד %<R_dcʄ%LO|~,ߞE1aDS㴙ba\+t=˞vt[E(|˂G}ElW+F֫͝EYn|Yo㦠֕O}Q l|騔ujw"~VlL pjJTbepXf6Pƞ1+G;.IIj]duEw]RF#tQ$I}6}`&$l$6#VeeeVfVveWfGGbpV&7~q}.ޢEԒk&DBu"]dt R$!UpϹAEjRUjqփeޓB<ϛ"@65N$cûѽ;ŏQ4$W9TqjBNyja.{eƄ҉Xo,,r_"/ZgZ8ZFe!sTdF FSP^i6X 8:Q|xahg/ &:!Ap 7@]9J>=NBcj& ]Ugv4Wǫ.j?%Izܔ+~f`.w8%a&Bq_txTE `kH绂i>ǿ![Sf9%M,Nd=efuM;`]$c) M&eq=RR`8ǫÀᜃU;ZM$6 P˧\|ITUMR9<- )֢_✬;y$K-)T=!  Bf)C, Ί'X};8aZ%д&xLJv䕷\]]m!kFp6 ;i;?V^sT¨@4Wl0G*HBу:EFwtD˄m:1{J1 ;JL6#e"G1=ƘʬwΡK35+X_~S~s4)}cF(yM! +)Ǧ,Wԝ A"X:Zy*IecRNN0سFDdz嗮 `%ՓaXtqn,I'ۉp6]h c*hs8fߜswl`;|} ?fn=0|en7]S@`[k>p])p4'k!|8 :ǮpNIV\J WνwE-DZyD$ j(-#G 1ʝf]|O7Nȭk!4LF3QВq: :lLqe zIK}:d:Ƽ(K֡vgA9'认/ R}+ۮklJGj"`Wp]Ohy=nY_.aA~)95^1=}Ds[n?g@^RE =|1(#-9qCcFF"i ƜVdKٻ&n|(r7>ijp%9a Db{I*]Bn$$qdγ!'ęWk5*`lCLWPlR ~ڔξ?I .UD^8ৢ7pҹ*̝\xq@Q Eyว'IA^ #_??> ViʓoY!‹v_Q^T dr`>BFffYVN+'[O޼sn%Gxk9]:* i(VrYH.I=B {{-W@qۇUq7@B %Ձ'ikLSQ%w}"bmmux`\\VSG^sqg|8Ja8y(&(Zek*7(lHzZf̡㥳~QV@_|pf6ʧ& Ƨeh['ާS:HW:+lA#9 S(qͼ:NO}<$sP# ɊMP@7 A&C@/s[>c8g !e)#T4B)se-=}?WI8{f3+F4>BQҢ4y9oO:,ԕY2 A= a}縴,7ԿbH"hRŽN{ W P/=EL _@S#'%pA«~utBQ/+s}=ޯu'9 i.=*W5+TOVzHZoƠ$eNSfZ*4}R`/jFW ~֞>nRTa(s.ޚWgiɡBa'{BR@_ZgvB%DFjbBTmC}tE3D,0e?bf28q䡚kܓ;#sYUΔ&thF~ըPen62v -y[ /7nHΔo6]Ŕ~iۍ7Q+rs.#!Ooo?%oO;χ<+X L?uW_C`[_t>W?h!__$)J} -IZE?n__em?ܸ>׵&T ID`3Ccmի'L_Hb){|T +@|:T _S}RbN<}2qMJ! Fs*gWzNNSWCɖ`*vaNEx͞ifs) t?2z>s28,\ladޕAx{Zv5l= O\& "swm@ Kp0Om‰|ex #\攧S_'=d^״K=*d1O?Y ZuVA+Lx MސŽlS-ݳ}D*g7;17V_[B՛L Cs\YX=qJ- CܮmlOhx< un2C0z.^՛S9JSgᚃ*E*k l&<ͭs]0+ T8FgEGF9RIH~[pFx9@ /ΒK/Tǵ&ͭDO\R ~xPztX*Zy1 ptp;2*`1 ̳CB79i55^ wϖgXsZWݭMBǠT(၂' yR%6FW#]gAmP\`_NɆnMS{ٽy͂2o楊-i*W{O՞.EXީ^ Fbvt^/?oqFoI{Ǘ2o͵D9񵞕u13$fX94);` !l>}֞7l=Fk8}Ӆ9h3 6 2Nyz˙^ Ϳr=Sȳi:=<Ӕ6 MԦBr/2rđmK]>r$f ӧN cm /$D,G%xt NО!nz#/nCp`)-\@4j3|)^Lvb:m=Mov)`"?ADh.{"J rLt!8%>Dk}ۮw2-ˠ':{ӮGZnT'ډs(jrHs8]X2}AKR ~m/_t=hA>t |G_{ n'OU+3h sA4^ s\xoS^<5KԱ*gkg.,&d.-/8_ԁr{9tyfjZ0XT^#H1~sϫ͋&Ֆ ϺrބT>s}j?>S(a>^d/iyC?B;ה΃h%⅖sN:8y؟kKp"gϱ@Ԭo9 Vav4tƼǡ%'gn^evrag-ɃneWQUPݞ ͼgSe19GNUN:}ƀJ3àG:-¢R<HETNcަu4jyi&"pശXx@@|H{hBKC19b!Z#5+b[!.I!_xhnǞ:D\k<)㨣cRK Ҟ 1bE X״t۠vOaB'e(ۍDk-@AbXcD/"PBIWyRӫ(c@ 19!X83(A`?+`:n-$9H w#Px6L3ѹ^hgEϋ2űlcA]y6Si7zwY-VbcL s&ҩ!y-| 6D<K724֓̄L#%`41D0o4C. bKs-}zlB=`[VHSP v oc;}th r%χفm>p>13XF1r!vEíS)Ӭ-#"' ~0o/kw@&=2R.| #YyCE}S h|q㾒XbQL{ niI3.s4O 0F5^o`| EW&w3iR̞@l,53/82e4DZtr,ی6bz춎9)Cpշs2_Q kXjoSsFr ;O#"R:G>4}ify-;s!Mx|UFM N~FgG#6q(7̗jQnԶI:\aAKZ JVileh8J6Ssbeȼf![nؼzWgtX*Xi)8N!0 mdOBa*Fu$Q',ZGZiE3C=8yTy4q$D8Y@ZkxbYQMh^/ Oxo0qh҈c Ň"Bg>|ZP9d[=ա$;^QxP.pB)?k%nCBD$BžS˥3uc(^PYtkY|!:H\>Wعnp3W}bYUTt>v7θ2=,08y]A>b=a`),жrd\!y43xj$I9d++_1"h5M8C:*$I[C:2۸.D4{pWL\CUfCqM Ӂkm2é_ CbX2bKpmMZ=oWɖl!YtfUL,4zÁd3<(,>P4fXb#=X V?T*8\j>խԎs%hs-TOGĩc%fg87@B}T5`/$c-iFIߵci7\zSiٟ?ڰ狑 ~{,^)~aY _159~OsGG-[;ٷblOc{X.GW~݇V;#D^ojo~̟Ϧ?DC ~19ȿؼӣ钃>tV4ݿuCzƷ}旽i߾c33,ߎ˵?PM귣MDx3~ /C|~ƴٜ-|G> w$?Gɇw/r#޻I/w~3jMY/ >Z^n!eN8PC*\ۿBcxB~ O7~Tx>%|?R`}_#^s=7lM]0|YH{ ٌuWQe[?8"! ]ľ#V)ȈȬnk7s_'tQUo/)MM*&m¢?M@NnI^yL&&?i¨E[9)\o2EUNĞPsW7CMXıѻmN|L&KfW;+ɯ{hij,w}fnT||{$j2ύ;țHEmۄǶC)w다&*#R:F'MuR=|w&\i'c'|;1_X4_uu]y}7:bEy\on" ˛ܽ>(걽W=WGʱsGJoɭwnܽRڮ]fWA?󵇷ǢrnL_"7Ipg_!{$WԎͼSy{ \yvt1]]ٹ3hȷN_{Tzla6B-?q2ܸv~̕.~Z'a|ۦ+rcdy~W><&UfL_'xo&nyk/\Ϸ۴Ө*m' z2;>_ͨwAeHݡ$zoIMq? _iJ2MgdA//@6c;8)XFQU_/ 1nMF8jFmzb1?ZZvr::J_'}+]Lꑡ鵞:,q7Sthux[ÿZR A +@!ϪsQy~9?0p$|ʵ̄e?``xzˬ߮5k=8v=5mNy{Fuuڿ*m4Ezص*[s>O x^q%š[) *oY._=4>ڃx I/ȃjy;­|rt[?v;*o7V\?2~kom)U 0 3d`Ez#rM؛)mu l>Nxyf0(k}M9Ng))`uf~g֦ru6Vix82`FF름k_rh_>@_:j[vM-Flը OgsoUVw= >tY˔ pW7t?:%J`$Pz} 12NEss:/އq!aC%|29"RX jcSGZA-hro~1n0Cym[P,ƒ|# 4*2us۰ż:YCu"vqh#롟db#`pe89w6g-*32jC/WnIt#\yYьfٓu0E ~esWarJMʠ"@XMoad  h:VASM 3Ql[Zڭ@]R}4 L^ .pN_GӚ0d{勨@JYt%8)즘^SB_ZQٚ5QH" P6 3S>RiL.o8N ́}aArJxhQ>vrn7d FX{V4,&p=+\82a&AC&;f 6"Qήb1/~Y[cqP,ߣjԇ.gVV4+C:XܬP("vvv)X krqt4|2`C Nlv]{8ʘ SlC" 2c dNmntgD .GK|v`ec.9(:# =MJ~M m5e_ s틲.I엎 }OZaRVe # .ߧ2"N%zK7`tM2i#{k(los˹^YMS3]ژEVn۠DUVlY댹dHҗNmFK hxm3gp-*'(j-|g$I0yvW/HHݭFYWe!x'%#񼝅c61"X=Ny T-Nh.` 9jAU~|KɾɭҎl#ҝ)uw3anYuZs"˻KzٍS/;Y< tى;n=}_kr ,bG9c*-r-2Ut.Y4rHAx6wm}踔ci;Eb1Uĥʘ5h{a|sXdnlOm {/V@R5B68E{V5OQYKamU4'r"ePRxdak`

T vŀ+m+.ZZEBZz ޠ(JS8_`LAw.jxMoP>ϦF(TbN^UUu-QOYO?hH?\ivM7t5`p(c SK(Y6lQx}]'̶@ Kd$ѣ"\rˎ8G:ݫ+G bj a"3>X@ѢF[|' ExMJu"x .Q!ի:͚Q).5B%eLʍS1Z1 mH&q4.ti{$6>FF~x t\dr{Te&TyPJ-+"e1/8F ^@Af16dE6eUD-UoJAK /,T3;G-2/ <PMɤUHTfۛ@E܇=. VGP/ L!r7N ]s"ŖR6<%5I*BWfFSsBq޾CK$&*M©w1qcͤ63llڅ k[`o1COE7KLt00&X+vXt"+uXrJb14v RXoJX~СZ$n3v%aU: L(5ehL,5qDw4ĵcAvz 6uѾFx)b\E8F>VRIG .h qp7fGh1\fۀs.vcٛ4gdT@M&Xhcб*CG-`y´lO١hu/F{<0 TQzao+|,e~!Hu`a-@/ -_е!Sκb[(8p;Ǻ&9* T- qy4%tR)wK{'XbT2r@0\-UALu9J05:kUf` r5 _k|ˮÖG3ð`Kr,r4+zIeM 43X1쓢PGlèEb;}V˒9r`\;ma <RSGR0'CսxA3(:Npmzor)&P;*X,[\J `|>c#5Yҙ-lk;bc["$bj?l}G2KqOtyQGxj3eO7 I -₍;xb᥁ίuW8w?H QnR~>7%F^"7ڐ.'b4'a`gM>;ON*6Js壂[Ejnކ4j=#vlKa&E32,b(9>zcfOhiax{AWAhՙd1.5u8d mh8AjJXz] ׇQg=N@A4blA,TSIj4 @E&*=g/@XۉqK LTP@^gE hÅ&,"eal>-Fӣ XV?Z.R RCKucH.k0On|xbұGDe -3Nh)9nEU&F;ѫce$9ErM Ƴ؄#N5 TKB}a) AuMf 8ì7ܐ9>ׄql]Z"G:pJ0~Y#`OkzԆ.uzYS O5 #&ǧOƺe dy *;+Zek,{K -H톇ӞZJi#thOy tzirrԼbZTůrqHQ*/3^(n/zIFN<%t( GTV&wbuVe"ДA!N}iz^`֙l &0΅.$/xqMM@!=;_JT:RU77))o`4VÆ C}+ՕtሑΒDXSa;09qJ F ])`jh'v p. t4"T:f9Z&av3_1Ҏ߷i>zf%v{v]5ycS{{'ϓfJ]^w㶍7mOY{[?>ND* "si+ɍםQHmCʟ/-mogOٍA74>(m'j#]" m|BM_&s?HĻF0wQn{L>&~jGycSMQzqO~݊Ez?꿃 vF8O.}0_Юi[&W}Tѵ&l @H'"ݫ;_8;oGxog<j?`'^l~Z6FZn§߅??6?#;?;粯4CǕȋ=:xï5c$*lߦW f|{Q?>,'>=*9,gy:?lHc-{Z#rj =D R6[|PsjY~*Ac|?s .&t {3fB!uJ-e W#s! Α 櫥b!a?z&UPIugffviB@s~HJؼVv!5d 6YO8&YtN9t)Z)@żg2cpUgs^ݏGߝm1A,s{轗08[S7]8t騼#=RWc^8f5'NwP?n! 3;ʻ.bJS[{^bOӱw^fn}ߜ}ybUpIyr$5\VQ{=甥Po ~1|q6[+Di{n1k5d7Qv+~;0~gU@4=>}Iz~Ϩ߆[I]X[oH~_Qj4t.5҂MmB x06 _b=e gVծv9թTߐnȱ 2[4]$wRudF x*cD/ĺz W(Y;142 2C ( b!#G:NFAcԒ SAUr'HŞ6顕㑛߾~xH 0v' nġ&Ԯ EyvG˙c%C1 PмGVk# e{JZ:fwhX }W0Ht"DObfˏ # S ЫQ7m~ u\ 0CU'w*aEHW뫋p}i+|oP̈q؈IrEwe~W_;f1i_6o,,}cSEQj:U3jStԳ<bFE6z ;5v\5֊GW\2w5iW(ӱP'u379*hh2]XCP);߯~6*lEe Q&IxP#2n9i|TלsBbg8j[,ҷߎ 85ҠL*=Ҩ[X?>mM * ڏ  L\*6PlJxihzi0_TϰuY? 9ueW5_ oB1z/0LQ;Z=3[g^Xe8oX|8b L;3:FtQnD"=gԡ,h)K̥_7.#UiS{TK06 q eXqQ cz~K1,ckeZ2aFIʓE*aT ˇ$҃*p&}|c麴°7/g 1PBtVůR%[<>؂#[ռy{u{W9j]l1uާG_:_p{2ӆ|l   E0xgIZ:!Oa/H=jQ}bXݱwc~ssa\WmH8AyoTHY=4J3u';堾 bĀs[9*\%BPNG  IHDRnMIDATx^?ha.\Z5=*IEO Rp$Hs8A$A8itA)-5Rܾ^Ky>;;TB&Y,rXd0_$Οk0{kƗ+yښL'ۋAk}{x #nޫ j-/njbc~Me15BUm \nE-:/WҌQX$033 J!8HI3{a72t`n( kP f;F/`vG)pki`/9|?n\ "Y+i <3O3D'`# tn7meMw U2ނV6 fycr3[J,e`zMoYLV&΀ rm. W|&d hbX ˕jKمRY |,K `L˫TTɑMWZ8p2 c E|XdƧ l)E6?؂,`b* #\,@@3hjTMՌ5}-e*~k%@lŪQUrUzu_/d[ʮl!Vm6W 7R%2A`pt}WBQHX,hۮ|ip !,F 2fj}pq=1pBNSh@9&9O6YyJQJG<,t-$ҰR^|y8GICNh|K H_vJt#,l! FxvJt!`&Dt8r @&[HnlywͬPi΅Dn8:/BLQ)*S*߼ L\l mM v7#Bޕ5BEIUG4yU{Y/'pⱑBr%` r6\:IО[iL_r=G^9x@![qRutQrƻL\T*USwf["Gw3JS8'e!ZUkJU~ƪ"Kצѥn40W1bH TdYHAAgѽw0Bxhg^TL_hȲٽsN|YVVR |Sr8{XJR9'4eV nB~S4%*A LpUGsN|xYV_-za]W=5I) s:;wt @g)Q 8ı[A=r|x4Te(8*yB[#܆vpr{|ق .p Xe{ҋT JA*l h4eA BoTJok)v4^>xBJ4Qտaݡ-m_v>~q_?GvB㔯,ȫX3yg%T MRj5p/NV&DSl %)MP*Q.\e*xk 4RJ<*|MLPҔɯ|_#k~0{#i..nrWJOJSҔ*_?JR¹O ;kDtͣ]+=D,âIENDB`PNG  IHDR@@`UIDATx^Q@FeIȀPMEA O-x6}.Leύy|x@oĈqgA{ 1c! /-B"b1q Y`u B%+bI0fFB2frcP(b<<\D:J=<<r=5|u%_S!W;5ϩ  NM_NuMLyIENDB`PNG  IHDR@@`UIDATx^=K#QNތ/F#ɺA [,)Y_-+a]A?ZY[m/"kgc{3NFb3ȝp<H) @gFl}7r~ !fd6] ! :" c Y\9 #$yn ;:[(AB@w H@1HE#<e" q'AtG,0V9 @5L (p $@绀9^(a4:ou_ 7 @4:o*!pHL4 y,`% bFPB""oD>1@o| "7?nw,vl ۶|doD:oEHNЄ2hB/4$?͘] KqO%7&4xy:>;XDS U̢[ n1@1 qh`:oeM(1ʉqI3^N5ӹ8t>AĸMHx;-O) m tIENDB`PNG  IHDR@@`UIDATx^͘mUgޛ!$-X-`/ R PF LmWWK`-E`A,TDQ:st8 Nw{.Os>}sv<ŃH@a53gP^W[uVq!o(d7jxW!qxy]U]L*3uǿw:NL3exT|r?uߙTP֞ ;@=NL}e xB&gJ"e|tܯx7@ i}MAJ٫GZH d tr&C@ @ @ @ @ @ @ @ @P@P %P8O h}&蔀XAӀiXAF@VsjZ4.9jv"XbԨP"8.%*Ԩ[T!GLHc+a(S'r+14SnejĮrY^DԩRɤ@a% Iy} fu@f  ^ BzK*N gGY#Ft^0 A \lLR8dSݧUwcg6E 8en?NH-vh6Z <̮VPv{\%t_kM̭SߚM hh* Z(";PsG 4x~MHjz!$9pV 7;`C1iΚĄ&)/yv~ے>JQϰF;X7"H"x XKytq &S9E(> kGgP)4x;I]NDԨP8ɣʯe9S?v=chҠ,!Qyp$p':ذb -MwxvwktǡkH*F<CdOCЁWѱϫ9(R%$w'h=ޟ)FL@EځF+N*E.spΕ/Rh+8 aK2/ 4l\5M/֊H:oZ>WIENDB`PNG  IHDR@@iq 4IDATx^[}lVW[BS*Z1AK"$$ؒjĎ!  I# ! FeP *J%Ӝ֛޼7'r99<<}y'(l?]$ ј= ALd2<~a_gsGj3Nã0nڵɛ7ov޽]?xxxx@{c^0>B!Bx}0{Lb7Ç q}< R 't\A;PF`#ZGqS@?|z3#s$͈c> q2, '$rKe X1?<1K`OI@;0}Oƣk'$d^To޼;wt8kEy0W;kJ]x衾)f=H8o.]i#GL=ʃcr]+BؓI$$IBwfyy}m@V=(xvCY!zݶt6[՝lZ'O}Wq|J隣8} )JeḸOAYt$ Hy4> GT_J: Oh{NW@@I>53Bh"e)L3Z׶P(.\l'Uz6mRju)HooP2*xIjW_f~?in93H`ذaҲw^>8 HBE,j9g_"H, ]رCV|Ne+^|ˊN,׏k׮f+++P[l[,sN'tC3 Yf#minnܾ}[qW< Y(|qcNB@]]6^IY^,F+: +Wt%@KON:FUUAN8ĊL5wh;sh!GUܹs`&WLpŊ#)f Y ,YY];w+ "{ |aƪkʕ+]gϞQC?VݻwR"H4hgo7ku(l***r%Iqü@' /xrv=gK2;++($ÒBW3N 0׵;$,@89?jH<|jnI"q]ٕf [2!耇n;ߧ`OjR]F00GaM}<1T; 7@`t-i2 B GU a71FUpD,-Wq~!>.і?%pD3k T`0w[-yfZ h5iOP:ɐu:Ȭ$d 2H$I^ڸ IENDB`PNG  IHDR@@`UIDATx^k]U{n*RK(BZ41ED-)Xl hhE$RIU8 ,:#M[9JV89Μ~zyHSoz cTTD*ԅJIy'$t7GqIK3'-tc}|LL^Io_j/ZRJԼY4ɒ- N;W,vknaK`ghp ,բYLPE PwN7nK4ht<-SJ[*mtj.Hj?b~s܍oj2"̂snuGә Uܿ ^~|y\f)ʘ 9~|9.iLdY dxTJ4q'8ieZHek+R #0C&5>pٕطlIkA=m "MaLEGc+la%up$Tפy%a'T)PBIIDRD^ɂJFtGմ`+{ ~fNzv#jZOk;[]XL*ѫpj聙~`n;?wL@Qv}D5 t./&Y+>T@Q1aU[G2A{1:&"{X@T(4ff"OfvwA9OvS0dS Z)zVXrPP "8@e٦٦.yH+|a]2T>sxݘHV%ɏ/)V>o:K1&pJ-`k_)QRT\]e:)JÀH{}X&mJGu [߾GxWٹgF' : ڌFDl^&Cb֘uN߷ȯdtqLI5_d-]1(A !3J nOYkp/fl|) <'44 SD-Gkڜ|Èj+O@iGn<OT#H\4 +$ROsʐv1b]8>ծwSNvl RPRE˝`xpEڜf_X#  6=hM,ZyKq!xmt.Z} \!jpY >ˠ\cqaCq7Cފ]kpvccp8 : c,,C4h(V|9^/_)[0(41 GqǺ݀)hЅbo5p $ɨU٭X݀,1,Ur8jmaO._@P6-k-RۡO#0 QaW՗?Qa ((k{JǏO@^0h J7X*?PR)IENDB`PNG  IHDR@@`U@IDATx^TWϹ3˲%PjڠZM)EDŨMcVcKBB"B@465ؔhզj",eؚA ڄ$twgg_$Lv/{{~3 %KU7%  E51F#ۂT>S5Ϸm3h GU[?cTeBH|E*T}7,S@Ck Ʈ[5Z1Ӱ#~'s+,kwb3fm8n QA4Po|0 n0պf/)DQS |643V{p=dN:唃!i6:H xcL[Mv[Nbg*)t>$sFU@nVF<NO &72;ѣ" %}6 {54EQlh)%Sz׀Zw9YkUT]>ڃWOrjGmsY̛ m{T0|嘤$[oPC6'{+NR7kJ; ST=7BzýJXda0<˕VW U fTLDoo)*^nrLTe޾gu8d V4v%*24&­@!@TLn1OsNS2@fq3Z -s@cYMNA!fjA*kxȑ-s1I>H(P}WᠳRdһMØ֎X?-3jvOU4P7fԨuNF٣Q`! U3M?<2JFmm]sڋIHUAݘ~#5u0& *@ Owa39fjQ/ ٭[Iw.(El~b Tא-Xn3𠽺AVFI/ƬVdYIrP&azf=V&ƨ8[2yC=ibls]%u6~m (GmU.8n$3PSnم}M~a,mb9ku<ԀeO,oU(W1ePq]υ6.cHs N_6K)u{lUSO׶@92RL}RF$^JZbh?D䈢LH ]u$4Td~7I!הbD4Bg!&w.( .R.w|I?ylNIENDB`PNG  IHDR@@`U/IDATx^}gu98YE؆2F7Xp4 Lة | k^d:QQsjli#8* W0.9p{E8{~/u z"Q2AQb k!r Q=>_. YzNAɽcr:/ 7|٘ӆAk5dB3*6W-s5qW1/0 dJoxAfUhf>T*O0 d gbH'D "5-FE+]k]!lwyfif\:owRGuom6i+DĺA@ĩoR 6Vp%ih:fuPJ .HgeS P(K|| '>-DQ \cf뻆> xG[:Oi2J d=g.̿_bȰ[`[,s5dB%}0}V horj2 (k.i?t@r[;o+lAY sBw駇V |Š~NKJ}2j}L ytqT"*, а>!@$6VJݠ$x6U^ 2. sz)crUgvZr7E<  t3wڣ]78 m-ϺSdD7opވ2o Q2kk'|\79!E)PM`҄ []X~uJ2(^VUZsQ&2h0=M[]8F=Ɉ DIƼ`!G\(~~mmE5 *;jݘ Ga Eﰟ R;v=`jRaGQl_k ?恨GZvqﵧHZCڒM?gaIUՕG^r_? *PUhCgFM휶_;)΄S>N۸V*@bRh^4]]eJh:cKǨxZI@,ׁ85'x\3 t3E4(v;'qi[@~\Q}Z5C@[⦡yCΓ9(-@WL>euF5YYb x7>j GO.ԩ/ݩ-qi.I) PsoBG&j& IH7!}ubpu=cP,IENDB`PNG  IHDR@@`UIDATx^kWﳷaŠ[VKTӆvA[nj( ZkS_5!ƘTIl$ o- A757ʂ\2?83q 'Dx~9y8|RtďbyOA9ʮBa"D"Dm~4y+  NDZ)|s#\"y!=\xSUmb0% D$iF @xp@.j6kRIIk#)Rd,yX]b,a4c9C JyIzp0ɟ U 訤SO$*@Z% Gic/JCB1s҃5I_);t!u V~1f,12$ai>Hoc{T;L#EԀN"A6Jxc/'m^3øfn`^;# !Ш7p'{H; _tݖ9]N3!Ec;J z*isщ'f2_="=jYUR/3; n]Κ'JGaɘBPi5MooKF3i1@3z e14ЮKLyNU; c+ڦ骤׿I+v`q?$*PZ/]pAd.^I׏'PM؂%T~N:lk%]>8|tKҰ^$<B(kckxZ@au{X&,e1, IIe.HڳXBX`3ya&djR vJ:s2L頝Vd`)_~OiGK7oMN&Kiq"5_5_ź_Kg.#Q撧DؤWYɚe%n@E&>O th% pkTL6+zSa[gO$-)#l4~d)S.覓t)Vb2^w $ !I)F,|'EPsaH:i /˔o"EF:O|\z2U,#N$it7 l$"$ VvH:]1+iک#d>\ly3,B]_>`_\xz"խ K*"SXIENDB`PNG  IHDR@@`UUIDATx^_OiVX ?&-AaC GoֽMz<1bVwP3=PO;s2!'y~̼s&֧~/T׀> +< w0/ۗG?#߯K~1KŃAT@8xJpCx<%xOxKxbx <pw"ll?<>fCm;0ZX)uP:(5;6k>,{\ƲԒ2VzpX {?}>9,s 䑓}|}[Xrz:6J3HaN 򑀼U_,~uj5 +਄D_BqH@J>,:*),n0q^q$#I1go/`; @j6ޜTMm:h(@*]%7+}*. ]:<pBa) g!I;=i>>E|y.? 7z0$rm%e@OBbJTC0q?[Q Q= cF BX+ƏX}#ۦclHZx `,~{( / ,EKi_WB[¶%D$Y76xAq_:\@ bގHB[%skvtP>T_^ԟ7?l5:}0aѬE {Nj6'^ ΅ $aiBiLx`1!#_ܦ;c^c].<O''! Gwx||8apw8h||'N \YrDZ*)k~_\bhp~uFm/1(a=ъ7qØIENDB`PNG  IHDR@@`UIDATx^ٻoUeY|Yvm+KDbPHHD(nґ*e7(E@J4q$ IlCj3Gc>r2srymGs9Y>N#8 QQ5TqxRL)FX~s@eÇƀA|µM(_!Sh4K[BF{e<1uζRM8OCa\/!ڄx9C !&,)@uFb@4h2O#@nƑϗ!*7wK}ޗ9wOs ouU_P8N?wa6&]%) 7lt(yL\?'` : FM~^kγ">}?&+Rc$r3!88IKt,^[]I1OJ%S&i2N3<-ܜP?Ma 2&)J_1w?SKx PG Wh-cv7'÷## 3.m+8 l Ą;^/_251K[P3 LyEL (`^/*~J 4X#T`Sr7!yc 5NZ =xizBI RŎ5@/ޢIE 2C8rѷK Ȓ#@dj {@[zR9n79V"Ujzߣ9.3F "]$ħ=2>!/3 =RcL2[@ӄQxnQZ3BH$dQ'̔54R0،RoC>_#:E{IENDB`PNG  IHDR@@`UIDATx^OKbQn?WMYX)%6Zͬi5ML+׽@ i{8nj|Co{3 >`B`SL)L{=v:s߇xD]'#*@oOT^c` ] r^&Xy` 'yp @0%@LBޔ`0!rޜ WjG}Y'K8@D=c:Y"aQR(Q:lMv{ӤN)8&,E, `-ؠ-lF K,RH 1MCG$9*B$WO7C(Ǒƀ1` ƀ1`_#>HBdO(0{kxߜ = v7,7{\}yVӇ$0GQ|C9fHY)iTY: reIi9>Eh] 1yN&s`7QK߇f*"o E9o [9o ļ}0xy&F#B:@ȐD5X<!o i|%'D?@eլIENDB`PNG  IHDR@@`UIDATx^MoU=db';-qj4IEP6HH "6l+D+|nUb^T$+M[5͛fp|S sѵ'Ds& `=9 y Q@(C1ft*n ! tRNK1= OAwncc8*q^ ԀG`2K{}2 ţHz505V3G G -\ST`R07Р*Gw_b SR@|ɼ|2aS Ą߾<53э!hB1rAyi=Z7!.(n7o'KBTG~kI ysu|;p~{ovv*i1@ _6%?tG&q^_9,++#{0OtH}3,H2M֌6SzwOdJ@<73Tc?v,Qn_,t,Sxx„p/.z?\*,LMVen`o«Cۇ>)=teW9_/&|\>1uR$ Wp>)qƖL o1+!=:dCBHs,Ӻr(nd <<*w_t1\#kR!@֎g) X8ݎIB-%@VKC,.:rTK\M*ei2g9GΈY "GKyYR?55Bk r6Ӕe27i2Y\?RCc L?Yrt>ĊIENDB`PNG  IHDR@@iq IDATx^[}LT)32"b T]-KYݏVݦJMvuUiMMhHmq7Q0.d5Y?¢Dc4l"ongrdy#Iړ}wι_j b1BLz،0R>|؁o2WQP000' 3%fӵ3>}###mpttghh mѽ˗/ϖd!”6چ?~ \k xs&]DL >FW- 5"AST[wr'220 *X4/*>'g${ZJ=:$ %_9!eu "HcANml4= r2B6ȖB)`"V?uF$h Ҳ"ōsRo~-V{P_A$ 20j/X@Wd腕', WYBmtB!ACee-s$ \ ټB@ZOoVھ@Z=8W-N{Ɇԭ ۀC|$ 2D?~z<_sH0QbzWnߞ%HCmGVnjp M HI*?O:4& >|x3/$H@4( ,]ٷo懀D~S}Tb<τ%7|ދ8Ì 56= @s=zT;VGٞ =ͣj$ۚ`nZ`ӹjժw H2HuB $Ipo VGԁ7. kw"֓!V`= `= Oʒ!'! Xd>LhlAE m6y>K #@dfflڴI<|p8**jr7E+>~>IDeNo=۶mRarh]^Ccv% U0HIN2AG-[SBhRL2P{r!$xv>RZKƍ;v(Ne}M{5OMM;vڵm/rbxv7QNt" _S~L X$9sF]C, gfNeKSyq…Bev}'O[Xdggˍʑt&`~Lx,"`մ*HT&g\}AW^$޾}[\~C^Јuʕ+744rØtvIFF! 7o$I-7+˗{v|:o_ȹsNogYqXr IIcc<!960EBB! 0o21r|0nܸ/=Kc9Hf%$F1RLĆ`ijj"_Tw3luWycijgJe<Rgܞl5}5;yt99lRe˖mDJ"*,}n{w!VؘU34b།apH!n]{ N>JZǹ$ZM@(̢xiw2b:n䙓#oN$X:ބ>O\PD/FlCxABcҥK\`F-~嶚Wƃo&0Iq3\l/g(%8D?xt4-l1f?ESO|pH_fZl[0?r/ް`'f|'x*/,^cDJxYF Wy:+[f$ {d<0Q&[.U "@j$? !<R/IENDB`PNG  IHDR@@`UIDATx^͘]h\E 4V1^ *ЪP(6*j+"*("*5B( MJJj"BբV"Es=0v؅p3sW~J_$x$  Xp biYEb\@",>D LFA6\Fp|($@@ >x*$' H\|" Ps*$y Z $ E SJ *H  *H  *H ?+Y$»%UWA_ ~$UWA_ ~$UWAs^@{%Fƒ>9Y8-Hg#xC0q[%ǬkEM*n"s4-dUӄ(RJ l =, DȲh!KHD25v>;b7 S熍.3BтjSIFЦO>!7!/߳ %,fe*jC Fp sM0tn[)QBBc 7$f{N G:N,nhg8@;&kB-˸bG4w*$ߍ#o(H2eYj# \ ( @DE4SC.#붓"@8}q|p#)S4Oc>Wrpn|FW*8 ;⊧'45s|Dq|Y)ᯙe<dߔvр7x)o3^Ə#4QY2E q:^郊* sq6A=]_xu<@pAnpq3/ntozFW5驗{n$@L: J̾掝}sa) (15^c@ag ɚxU'ЪP @&o/ޑ"DMX#P3- $b\(C[_[w/HIENDB`PNG  IHDR@@iqoIDATx?AGAPR)z] moO`tjwǥ (jl,mBB}&TDɼx;RfwGgg^緻;3?x|@@ukM>ԤiPyc ~P(I"%{^1 AD"wZ`>f0$ߨdtd2Q+s)t)=F wtCd٤Q:͆ӸX(+u[{n7yS!_-K&lX8X=5:T*,s:ҙ%"~T<zOSZ^mh ™yq Ж&_?ț4O^/LkET*y|\6k[P Vy Yx|`dX.!gq8%&>\,z^_2TѬ^p{zOtup8T*WB;R,?*} ĥҽ;2?*zK,-14}߳X,!x3{x=KĘ_>IENDB`PNG  IHDR@@`UIDATx^kp\u'ͽͥMLڦ@[ZjahT0QGp83T `gE={kdJQK n6K6o|=xvMO/$9˳"|| be$[%lQ|9'R {V׶ϵ0R y(YY:W OS`f2 ;4C1!3ϓ_/q T LQ0̔{J }*ngˢ1nf d"..1 ooU#))66 WJ߇mic#? {U|C-Η={5eEp:ou FD|yBTZ7ǤR$&@M@, /&9&+r)C6qx(`GI 6yR,ՉVa|HϔƜHS s㸖pGcП6nqH=ڀR 2 E`#KǚMNMѦ3nBğ-ݖI(O.39 1썻Mݣ{:A;k|T`C%)t;ΗvC{slyMxrwpZf Y:~߸'I1s:>skUZtifYdܥaÝtpթ[fowwjZ=X~e1[]@< I15N3i+7=іd/X@rj,۰@ʤ$&0'ƞ6w)⌻)^R%Ūl%xeP qOSsEN-BB!KB %. WRmf\  =vj]Zm,=-{wfI$NZCV4Ǝn$-#NёPGdHx2Dg?izbw sdbϭz*U %438Lqg@sp~ Re%yET( ^OzG2V<Ï%=с!͋,R"ղ|Ȝs"$^ڰrdX߶X^m}0gN|\"cIENDB`PNG  IHDR@@`UIDATx^{pT޻]!<" "i vCSe:V T )#vZP_V( J #nv=_3sf!܌o=|sX`R#D^>( u`S+T.nI+,Mn]#2ᔻGuN!D] VO:BQ(hl]彯BҴ A# ^Kt.`LJ<1|U yש##ڃaR&o}0wP(\7:/޹{X#p~SM &Ws?}U:Eţ}ko>Ne(}~o|顅!̊q nhl"v;{3w pPXQͅÍZ=ƬTE|\ԠxTOhw݄g"GܲV,.72X,0'џ>pOj2 /(+K_k, @ێYaOWO~bNoS1jvʂLҏ CgkvXѐDϽXaVQK zzvd\ij=9#K n^F%_VT॑AXe6l* A'/hbXVH4 h٧R}e5)DBXe }:7Lh/pu47 rߴ 6luE釛8vahS:""M&}An?JBp.Izr>B^~aPB2 Q >yR!8! ڄAX \ HB _X2S2!ς-PEӆV*Y%"'XzAч -APSH_od*Zy>Crp!iE8nIkX Q+ 4}uKyoKHy(߉`ﰜMsw0"V@Wqݓ>c`.H TMكPA[ Xm81+:˭}FdWɣ$Վ`(IF=k$MHI(hu<Y2Uzt"Pne U!a3E,ಂblz)?]! xTQY@.,a:c[F1S]&VQ@޽?jQGW&c˳fT0 ʝP vռiD[\ (Dw| Io>齡lZPjc43&zLݼ"iN" ɒ!MWΪ]WL0Hr2 D(@m+׌=$^aIṳ?ppK<9?)͌#h@:(2j+/_N-G4h3GʙYЩIDh|̲_shV5 UJ6ڼTS-j6u11t e< *Knqکe"-{3NŃ&639OFhy&TtwD*J%<d.ŅտeR#^..* A"Ѐ(ﬖAV1Á q\lj0&qM8v9Y\vO0mցCe}:B<:|6!v:Dh8HBO#hBOdOSAPym(MYWnJ mJU%5 x\c6n{sf_sЫ֞ܗIENDB`PNG  IHDRnMIDATx^=kQ\I6.;! BFJ^H/ ~-VJ A|Y=rafb`?BЊA6Wp$ G a2yiGP%Ϝ;x"ӓ0 Y$e"!# C JEIdHLjDRGFbQ*!^1(˜."=!U5~yC=Β:tjw̒BcXt\g81晡@">=,BHN9B9EE)غ]=Ug@Zl@ +k5zvPu2͡/rћB=&%i"mf7NЧKJ=ޟߏ5CwcHp$I qEl:HʉIENDB`PNG  IHDRcIDATx^KSa;grH#5Њ.AWA8m"/E n 궼A, <|e9ǣ^<;"=SJƙNňXWI¡25lV\Noh4m03ֱϨL&˺SP55b$̱>??[HL]T$&_r@9sbb"GcpގDBeSSSt. D؟yĒZ |=HFN&###a|DOPq#O YO_Ye0.CQ*0oY@? (fow=O*@IENDB`PNG  IHDRcIDATxc Q1-ab YgE@\  KCEԲj1_jL($Oq* A y:& K%u< baЀQ0 7c$j\IENDB`PNG  IHDRnMIDATx^=hqrIZ&& hM}B qt*)8Hq"88[!"Ep%jN? LW1MKz$iA,GKFI3QR8ǦF.B/Bٞ>բZu]CSeQ>䌸Bx^ť ^l<J Y˔qIrۅw}9q.zuy#b&|b&(B|G̏m(U#JD9|$#b"Ef_rs!n!~2xvη_I1.1)pRY<`?(/eC@2cԘ–IS!K覗~l("'񿺏F\Q/IENDB`PNG  IHDRnMIDATx^=kQ߽3hb̺DbwQ,T"Z QB,*XD/us$s1H9ýh?` Er*%q}p257{mj-bxkbH诓> fk`N`_+e94!S$ #r_j4I@"ȉ,hUMO#nC!HZ#sr#A3bANwVk*晤F$i^1Sy0,\P˭LJ-  .rIENDB`PNG  IHDRcIDATxA 0E3YPp Jn A VieYQ30L$H|ڬe!KLXk ?1j=i8䧶mwIEdhT @8i" Jro?*B*!*!Q<&5׹X]?;O"WTdIM~"H}©=ߗ(!kIENDB`PNG  IHDRnMEIDATx^б@.`Xm4 gW{sX-x7  \  !"B0Ϲ5֜sČicv{DI"@JzZay"& X`9,p *y2E9 vFhC袡0om%{~rD #pm' VX7XӚ]/Fu) 5UgB:3X3_ (&tוI$"P 8Dg{Ф-P'a OGy?$3BGIENDB`PNG  IHDRnM[IDATx^ԱJPrIriҒdf*ugP tWp(եJjlʱJBCn"bpЉ(lb>GYMnk2$fs ^8${ED4|01@} 3hI,J"_Ͻkġ*ҕpp3Ñ^h<fh,dH'M MV(RmQJs4 VpPXh بlrI~&F.!ZD/J$M\YS&6V`'6PD҈ZǣJ y@auP1Yb"IENDB`PNG  IHDRnMDIDATx^1n0߄HUh;0!1u* S9TU[T-C0Mp$/Gl=)R}>?h3jN69#0xMdLDm@9L}' >BD3vjCP)pb iס6N b1.փ{#Nm$%=){?є|nBūaprq0i f@Z. !;Ѕ~z`J(γq^Pe /vDr IENDB`PNG  IHDRnMYIDATx^ԱJ`$-*-ikjm} >B ]wnNwAi R{ppg IFb@hwO6$Q` ߯A:88x}Hd,N!8= 0NHp"Xik^zkB2gMM߿$Ittg|p*:xH^oϙ yPR"Q^Z# oկL"YR$1Ӧ]ϓw?ih0 f/:66 .GQ4q%~_7DP0RC'_zꂿ7gɅCq)uK=OTƿU2{:wߧ}N(xj$uQh'`?QDL(oMh:_ݣ'իƿ;WpvqOfql3Q3uOw}77;!_7E~#&̍:iߚ}>r~O]!oO>($ٿ~W b3 $lyy|DL^[/ȳޯTOľBD%Jh  ֠]J~4<"§``Ѿ³8WR F4 &4,fO@\ܢ|Oe8A&v?BJJb?iZQ2v!=jȈe}m`2?;koW0>|Z3E?wGsNNhECVƏp殺(` 2<=Xֳ݉.|"iwGMeK\tO[>h #J(]<ԫ}s>ǵDW +.|x9YϽl娂Hc6xs˳A/ n2$Aa_/* @w3ɣwg1 UR)hL;0CJ}-K2y^Р4 >y*2[Fzk@r(,0c/ا(|lG65@ʿď9nhxlVG#K꯯Oi\W9gw_5~DŽ}ǷOr K d[DG%(WK?Qfye wÙ7!\h/@r%c0:\Q̝O,^bmǯ?5[^>n_/M o? p,尟nϙuZirwFc-7ـϛ}>f]˫ w5&2|1nem'|Kɗv>|jadLT4xU1o qN*7 B/}-3~lu~\9иIMOk>:}J> `%%_3~Ek8+1ɦ-|˱&3\-? ]]Jv{j&V49k=]~P5&D~A?IaJ+f9-7c6@8"e<7:T݋R6(>~Dɟ6wI5᠖yeP Y*ky,iee?3}<,ň_ˏXj 4AhJ:ac9yOiVw1IkxGN2 l!09*VLyMPNd|^x<ƌH?qN)M) q-d#JĽRaZ ^[scn wIU' I(},>5xhA 뭅}=P*샏6ʼn(4A ~\ݛL[xRPt _~<c5Gl1݁7,Ycs<ߋ#h"Gyss ;r.H5Ok<Fg9'?ic%k 8r>8p~2%Jay2'O<o:uH0aJ3v@ VӲ^6Ϡ!"B[6_3KS%oy#_!sP>s`ѭoBx/1wG<-ns*m#}ad3$ƣS/O `Ujت[&~3Ɩ5ۗL o_=b *lH猯5cײl`#h'|3@fvz_ cXeڨ2bË_5vs~} 0]\~)#ERDw}8bm<`G_%IENDB`PNG  IHDRnMIDATx^KTa}љҌi2* *h!ZE pW:آE`IpPA/]-LT6c"!j 8b#njqa-#]˰csvyec-%7YeVfR&i*GxiyV:t^48BDۃ3}$u 2: |CO{>L_ɿH_s1"Zh'[}{l[FM&NiKɼSV^* "{@3O.>p{_{mG I!41m|b4YA?||liSIENDB`PNG  IHDR7IDATxڽ 0 De _PY JҤ+# {ȀCdməBIENDB`PNG  IHDRAZRIDATx^a @ao] 'ZHmDTOHP%E#^а?c(AȊ߭ _镚po¢l'IENDB`PNG  IHDRAZIDATx^A@ E{&Cx <;& ^d@b7 FAȒ(lj%9&ZV ѮID.NGG@^lJu%9Q#Tr@T+^SBWV/Ƌ{oǙN8-IENDB`PNG  IHDRAZIDATx^}A @ EsA0=Wh]h5 ]KBi!۫I,ZYg޴pb`"t"Rt.4Z:#J@Zk aoR ӦG>pn PJ{F->/n\МNޚIENDB`PNG  IHDR7IDATx^ˊ@BtHK@ x]hw4]k1ϮU{0:9eq yȒ$܄K!`-V. 2 h9T+FH/lTR#{h$Je^%JgyHM|AIENDB`PNG  IHDR7IDATx^͡BAᯜE,TLٌ,> bC\}_9,~S3=}>tBN-p$#I8d 9VVH@#Q% aL5TW;FQUdÒBQp0f,R237?dw$uIENDB`PNG  IHDR7IDATx!nagF` m8C O 8W (!Z B!̾h-7һR{=5.fV iu"d lSuuh+l+RȀaJ2FPCʷ0:VԒ0+d9Kz 'ݔRdji¯ҏxY@#[HvaIENDB`PNG  IHDR sEIDATx^ 4PJ@) ^,. JT' ` @ -4 dM JIENDB`PNG  IHDR@@`UpIDATx^ @t6 !@ x@,C01$8 @$8 @N @ @T="xH!IENDB`PNG  IHDRUIDATxc  +P>+- K 碦e=PTLćRӲPCĥ⯩f,Qn6_FCiSb5A$k)je@~+'T3|&K$딖 W `ZYgIENDB`PNG  IHDRUIDATxc  o>+W |Vj[A@*EMzb5復eJKA_S2Xᗣm 2ӦIJk H(>R]ˀV aOgz )>M Hg)-Aip 2$(- 'IENDB`PNG  IHDRUIDATxc  8+P>+- K 碦e=PTLćRӲPCĥ⯩f,Qn6_FCiSb5A$k)je@~+'T3|&K$딖 W `"{hIENDB`PNG  IHDRUIDATxc A&V ;@DCԶ ,?06T@ jP1 *KM^C Be /G%@|d! UMe@Q|@DòPR|6@.ϮSZ\!Ң+dHQ0 5@c͊IENDB`PNG  IHDRUIDATxc eV ;@DCԶ ,?06T@ jP1 *KM^C Be /G%@|d! UMe@Q|@DòPR|6@.ϮSZ\!Ң+dHQ0 P7ڃIENDB`PNG  IHDRUIDATxc .V ;@DCԶ ,?06T@ jP1 *KM^C Be /G%@|d! UMe@Q|@DòPR|6@.ϮSZ\!Ң+dHQ0 =tB;IENDB`PNG  IHDR'<IDATx^ԱKUaxa!C2)(hn 4U 5!Ys:8AC6TFf_K\9o:;>Pۨg_lౚ(VD̺Đ3 ӚU츰OS۔o.(25"ni,R=:Yӑco YN$יaG!L:c9~s{"Ӕ"4ԓc>!>j"WOZ2`A*f@4[J[ʰAKTVe#-aC[7^5,3XHKYC~Uv[YBxw iMWoRim֫%B[X۷+ZnSd~lW5rWٰEuf*\#Q U{麰_ˀE3~PyV'>-9+0! n',IENDB`PNG  IHDR'<IDATx^ԱKUQA> + AIAAscQ >( ɚpp>iM-ip"^νp eFpHjGOZ3!S[uQf)]R2m&--Zv[Kvb9Z-ƬHViϙwü$'IudU"IgsfB2oN@dMy$B_zrfU''Y͙C"\JIRT#Ȁ̂ ]𼜳$UAKL~k| *ٸu㭆+_z%v$_իem۬+!<ֻ V3'6&!.Y@]ҙb,;-?ovmq_șa ֙qG,aZ{uQ䧼`n 5 صI.ӄ6Qcpˈr@bp`IENDB`PNG  IHDR'<IDATx^MKTQ8ch9BL Z 2 @jad:ʅ}.EjS!A pN"98'4♃>x"шU3n.1pҔz+vBد.6雋Lń%Eˎ{c_ZزzuxmF-Kj˱P9I!Ig1+z grl\2gVr_dPrlEһ9ꕬXAx!r%8*#Ȑ~R13輧!ߢTb X z!mU|jl̚VwJZ)t8\W_廹ymm[TRhH,+[bT-9o;U@5y6䣁iEaMi+. vmK0"QO|[rNiXM VK?\IENDB`PNG  IHDR-|BIDATx \U0pW` (TJjֶ^,ݴlrW@ݷԼ ZY! 7p}y|g<|g˷a@TbŊ6 n6 nP+QSC T(ȗ75nm"nT`sTɰ:u*bÙ0?"ftѬL 5sRCҬ{+O]bDu{#Kc 7\"Ų$?s g {:Y\ OE3{Cba]ykX9߭zT`'гM8|zm(i:a -Z[J,JГ:Ơ6*Rlj2ʾ}hˍFX݀%`|ע6S;WeWr;#]ͷQDmu\kNG+ܪ .zm[Ug]Zj-[4ϙ̌MW%/,nnYtH)͇*t‡ O]4uh5RݨF! 'kz! tifڢfZ%ߎF/S o(.6,*n4Eoz)DojZu:XA@NΪUe>cTR]н6gӖ/X7nKu#;cP1?i5Zc3O_4Qce8c 6Ve>'Xb*/U-,]4HY4ˣ3AD(EZkdckVT >]y~go` ƒg)4۳gtCF KNMP>V.8Եٴ*3"K~Jr@'?b|(kS[HE"##CyDL^Lyyy7qeee5ֶMc} >! FW_xcE-ncbEV5f\vQ}K[u43@."Yl]Xiii=zMdM}k]]/\w_XXju]C1]JJJ0y1.G,<^$t10uAt1$̯Xr#Kߕ沣VַW@wCi]+P(`eYUҤ){ ]LJF8Ʋ`@No˪ LJ =bnQ)?-1j2Um,#*e֬JD`E뇴Nfi@>ޛ۬P7Yޠkv6Zoͺ?M,Z*tmޅܩ̯R,߼P67:׶Ѻ2;!9U؛xuysrHA濂vK|9%I$UiAi>s8˙/gNΐ/v:wTY[nH°zbz̍9t-4W,}q"O#ol˺&zt޶Zßԇ  D 7p V14',[^S_QQ /89|`E5L.W>l=w?8?&(SmA)Skd)Q+7ΈJ% X,pQTT`4掟UUOW.Ι MQ=蝠abNYROWYY_۱D#o\XtwXpÍ9k-#?NY}ay#9mO s٬7crr/90yx]]"x^ ]Յ#][]=xey_taV_Wˉ=5ѓ>,\vGΓDWPf#8l>sF\f rf\_Mq² JRy8'ffYkF3ޘDd+!YQv|,wuǁvoh`y԰_B :dɣ[MFK%U4urӋ!_P7Ro47Z:Iy5Ԋ{-Ntڛjzޛ令བE]{:[S {GN|'xvjyʃs# 98߈sZ*9Hx˛ZF`?Ky.gD2l<bKϊބoQ֏R~4|i e0&XtĚ+K°BV NXl]"XAWki'9atKk|e(5S&Kb ͹)PBٴ]D,XX˜7<ɠR0ok.s33] 5;~ yXy'kr^#3n֙'ù嗒!n$EQ,O&ak1)dI!"6%˟];8Y+X. ?Ry:p7X.tqATul]\fuCP+f_In[뮌Rʫpn۬!>,`QTep ͻ~Y}[MI)|9=KHJfdtMs>JlwBŜd].Έ|]Nu  8Z-:sjL@Ç/aSM$ì26`∵d]eetSЎ%i@W3A 1k zXZܞ%XY4)⹜.j(tꌅ/K}4C ٬j;M][xmIP'|4|`u2^>z؁.+K]j8Cob]/p.vko\\eÚ.2xsˌrr~C }(WCb5 !Q͖~\l|frӰy7'?\ˇJC XxkΗ xeF v`աOWژhM@ bcU`1]>#Ų-9}Zb{CC*m,Q%<ϰT֯~}жi]Sx9(g9?oo=>jWˏ3 m׌Nz6{s᳔vZvm cFQcUѣ}m%%%.-ps|i[.~Mt-a{d "ˡÇXo۱v*ȲtY 렃OwYj,uXbw.\?*y~o?Li'o'F8g,YI^{ ;; ]Y‡Y#XsS]xQnkV96<$qn?BP΍z,fz7p1fѨ橷ᬏ)etiIdk7,_䅂:ꥆz0 7(vHeDY﷟9prA|!2TE!ClNxrSڌ3_Qpw gR*DЧ׌$Xz`bf=f8,e++;;;.NY0^ʃM`Q[N mNX};cyTc4j z.V+o5yQsFaX k xh tXYFqX}8f){YЍj'ZW_Y?5> :7+kO|1]׮ "4{O\FEFfAn f! k1K XN&uMLFK/ 1Ƭ쒕Y:`!`bXs"7[1xaXokzcyڇ6]0>Bi>HlCydU*kܦ?f19\iIo~e=QwO䣏Ҏ5F~AjׄEaob֤4ӥsH+k 'NVCڕ+W^n>Ɵ7 7 b%M6 z$}$DXV̪HFʨAG$`.:ayR_,L0j;]`~T_ 5 ^ iӧ1K fՁ7FpdE`}kXm/: ]Y;6ojz`iKE 4UCY6m^:^yoXetРA]'M$cdEرNt`Ⱥ!+7.4E;:Bsّx΍_:=ȨM+tF 2(D4pR"?V]EN58yPHI1"e\~Z3<Ĭabn #RT۴y2=^ Vjܼ2yFj:)ڪZbj])Y&2v]!V( + ]AC;ZKUf!x~/,\Ck澆 lcoZ=_>GM PYS~wl*,fMy͕*ke(O0{X9O|lհ_V[}4y ɲK76#ǠY ob*6a^.Kو'NڟM2R2M771߯Gg7Rŧ)xc=ΰJXY"`XbPCGstƒƫj8=NXrOXʧG54Q.7YװKlF`պ)K~ fEO$Ki7HϝgZ )~?J%keK_-isV=T m,' $u1G;5@,xu ى.ި|5`n mTԯNL[Lf}ZҺMUpG0ȰV#oڧ&˂>YA;!=;8!Eiʶdɒ2lLaa'o߾ ¿`ߘn֨jܾ}׸{Y{uJF:X[[Kuk=v jh&Rn8oeKFn5T} ^rXY0^j+رc7KKK9g n^M`B rz V9!Yk 5l,..&JkR!jhE7HuWQWЌzͽԨx 1\.++gƆ j{1 ^)RyȰj,R5db<o`MtsRCEj~QTX9]g`q=_U AUVJm3%ǾLćuy4~ЕG՞t N}+ՕuV]*plFU0Hv.C @:5G5tTu}CB,]Ov="bF($EGo?@n~ٲנָmzRjE9^ͺzz6[FUzE|Ax~dQ7Oz'AXP_xR{"a*1*Ň_ _khM'X9 ,KRtر'D16Y.D*7V+gJy/13[@XGw_W.k cuA uu%4 &`l2aX%# 0^0jT|.y`I /a4yH{^ߟL s٦KHFu'I_BF?QoٞXB 6]PC i]'jn#%t 'g"iD E\cރަ^⩷x%u# (8 e~`Iӧ]ZlNBA˰{wNϖ23ug,X1Dj"GHbcc$Xj}JIta JӇ`kﰈP*%Vi]RP.0"iV]`!` :$uѣG",Vzi8Ri]B;EW*zeWk_o&5CtZ/E*qÖ7\(2b܀AU/%A^,x%Ejmm,RsYш'gjXPIXfƐ hl_{z4֥0,$m$rG]bce̢ ݍ.<^͐7Dc z%gj(JCKH(xI"{G_0^t cHNCQ ugefG@`|6z6'"J G9Xs>W=]xp;:#bP\ZZz%...:111$!!Axȑ6O?1 §v[ o\?SRRR_Rm`{'蓖 KpLsIj+NhBjC &K5naj%B2)WO5XRQME53^j8$5' [y1o;xRRsű+k_D2a ŕ7>Gj.OKg셲PxRyp!RB_Y XiR뺍ENtj'>NxsVurYYlbR~(8b!veŅ+kB 5$)WJINJIP'QC`],V4B,KY7Ohh`O1ae!TIϵ zѥ]u$rװމkx:މިĺf/R>uU2=V)oT )H%2$[K8-dTY$ʈ_SB'ךBq".cogHrG ;Vjxa75&^lY֭[0ϟ??L~T*3%%B/uzL(ɂNjw<={6}r~~%KTaGgGtccO/^R5dQ տOّkQmo}Ic,Nu) q=a!\}I͔ct ]׹b qB`-.dA`4NY F|N`հXX,]U$X*C.ZC|X6]&xbt67 7/u4x~l,sb` %uSBuKnW*;OXRuP&%ġsfGh5=֯<1k%"mJu]ٜ6 +oGb:tfXAp]$+(((8q'EQF(k YI+^&-;{9sB<y`M cl]M q=ɵxqIW!?VDsbӵpQ&PhP%Ӝ(ֵj(VjP%1K|TIFfѺ²KV00KDeE; g]]dE%V>!d+7dYxx>6w @ˌo]{JI{# Lu!f!u$Pžˤ<˞W',{Xt=s = rss333666"RDh?:eSO^e!Gk={hRRY/xɢqRLLץsgtfa}K O^w[WLZЁkxԎOYHѬP"'p.: w66%#2˔¯}o^% XK>,WD]; tb{(埒YreX?aꍻ<. X`꠆xX.Z ^w#u0٥:K\exEa?p+ {^ruCNtў9nlԐkϳD|fT>|{w5,}~Qԕ9dUfY,Z I<|-;5NLXNX,VGy!1`L"ŚPp5Tb0hX+<9?he/IQ;Yb|ҥceiՉ.Y{,la pY= YA25I׷ALW@S]xCKA:?,MjH֣6·1_S~b9bȔk=%=H5u}4U"%~Jii,[p.Ba-pĂXYŊ⣆X=ӣ;󋫹,9@5w{4C%DёWMQNQlo=V{Jth)þWL~yW˖[ ,z.SU8G3g2C-f#uu̲uZw׃2I@5eLa!ji u^!μI~jkrw0 tY^3-B1kO;ktqRntbI겫!iֻ75Z̯WM >*3V3(*.zwXH,CgG8m,?}rwEtOUo!~Gx_ʓ.Y/vGqg&.0Ju5aKce5R+XJe A#2X^e ,./|PkX>tWE)#ݹ!//5pji-ky췶h}Y3Ty_MÅNXFg#YFVֺb<0ʥ௨ +cT9a ҿ_XQR7=\줃[E\)be.eLh(YSHRV6a{MqV EXV]Z[Aٺ<]Yzt]{ʶP6+ަ[W~tc;%+ 8cFGxQ?_(WKɐu29gsŚP?$zÚi儥sSG}Ty?쉼ټ`_ kJzxsn<\D7ӌozХ'?bMh"@2!Hzs!>I;|p4@F12>$ጅ= k,Ouܧ,\Ñe>dXp}xtZV7Y4Q/د;`MeXAX}QRm>H Zj4&pS,ə˵|,9fp钊EhpZT2GÏsšH*& LWV,Vvǧ.$ҕÿ nYY}ZNL Pe荴Wvuy,yvaM9c44 KoL|l΃5s>g͠3B]b@PzRN 7`~%:a%M@C6Z u38蟘5 4 K6\K~c6U2T#:@ZCNرT}~;X,Aք?3R3>0v|e/,]z/;, đw abt@ !EF~0^k!Sk,\;PkTVoDkHOeFB"w5 a;Ku:i1l9ozu٬}A.zu7{yR!RO%1?QzGyHgO}=[/k%)-ÞyXQvrOdQ\3,)3:Wz|d#Q.t?ڄHSA-F*^Y78`a]{972Y_s фwX%kn}k󷞻0E]V7lZ AM==z\*C?ȺvfZa] ZCOu}dvRYrz T7^+3kSDY hf2r[XZ:j+*1!5' ]%*|Guk`vpŸ];yvVL.E"!DJkBD-^;fCZ%je7q߫ԅY\; ttҬPKՅºt ۇ7k.hn;,|xmJ+$q,]4 ƫ-P<_}^]<3略[wk XY;$DYڵ\gA=E'Gz IsvϬg}}[\l]yjG!{6 .ϓ{'"Ʋy.7`7?`<N\!$.rC )з}Qn-ך8g5U#]7)AMOⲂ?QsS 3U(L%G5% vhGš-W9b:^-G6Y-|5p@O5ɳVgZ϶Ĉ(*XYi'Xۺ%'74Ma5aIj+OAW!。G3F<>kK,d%J+-K,EÛclgi `ZxIk+K嗬yC ,EÛ g:bI vVct[bЇOmȟjdibE,Ѡ+XV]lVR~K>l7mi&{JkhcA-{5[< { !BvA'v'6.ZExQP9=5-7m#&'>*tX+Id}]O? _<6|Q۱ue7}nP#^u|5'3IENDB`PNG  IHDRUIDATxc  b0+W |VZX 1,T5x/^zԲtKXpR m 2ӦIJk HDC2 ?hzX*^>BF%uJK+DZt\ 0 F8 * IENDB`PNG  IHDRUIDATxc  a<+W |VZX 1,T5x/^zԲtKXpR m 2ӦIJk HDC2 ?hzX*^>BF%uJK+DZt\ 0 F"(WjkIENDB`PNG  IHDRUIDATxc +W |VZX 1,T5x/^zԲtKXpR m 2ӦIJk HDC2 ?hzX*^>BF%uJK+DZt\ 0 Fj.-IENDB`PNG  IHDR i,IDATx^͔JQG] &f b `.c"6,EA`u{?>w1-ZL eD2I ^_MxWV=> X^ZP!"U 3m}xY8=T5eW̃\|v5"{y@Ia$O.%R4%2Y-Y R!42 (5h0PYAGYbXY즛2![mF03 g_6zIENDB`PNG  IHDR iEIDATx^͔=K@ًY]!(ZVF m,-k[Vb!E]4qvBqCg3cPa0vWmٺT9Hyvrt 13=7Z3ecvAepp4ܣBCmQh@0F ġB*$7Aibka>XDŔ~"USDf_v\&RU3qm$=. ?V<q$`m.ΥRK#/[Y%&}w/oyU/AIENDB`PNG  IHDRFrIDATxcOdX|alYKTXZϔpXgSlLXU179={Tv~S 4ǯHjN-jUXrۆL>C8LQIENDB`PNG  IHDRFIDATx^A 0FX{' +xHɔP:"`ԣ<2„|LGkphYR#FYQrX3ڈY$֐?l2AFs1zGn-nwF\'^J؂IENDB`PNG  IHDRFIDATx^1 @F"X'6E]C0"Xl,V^6_IA\͑ITC-b1ukq(0^yTAF(xOJ ڶRL&phЪpL!D~}=؀{޴W;%뫲]ԼS\/889Di6Wy%p^ Wy%p^ WJ`(QF %0J`(QF %0J`(QF %0J`(QF D?6pIENDB`PNG  IHDR00*l PLTE8;tRNS\TIDATx^DZ  0<\y/: w~!{&fGjb쑚!{&fGjb쑚!{&f ~6 %IENDB`PNG  IHDRKIDATx^ձPaρTj"łxI#/b0x%T]T4M=/KBmH*24"p~bo8ʩh@ v2P!7(+P@B@e @ Q P$8S \)p xD{dt)P@ p"R 0"tI.;b\ʹӁG@Y} 0ײ EOQ._Er7/666! [< ݂US.H(*r$(djBXtOOOobܔJ- Eű-J_D]_ω|)/y^](`g_%S|jNVX<Uws F;a}U;.T&9 IxE./ \Ymw1^D/O_މwW}\G{87|>h L|';5oᏐF-3ߜKGyqc3V!JgWdTgRhhhLt6}4ϩ$3=lSrNmNa{fq秖xkZG#?ese GfݑHĚCC^,ZZma``F/Lϊ44tY1'F688hZ1,^__pu^΅ZR(>M$}ccc{:]Y~q7)Sl&Z9IENDB`PNG  IHDRcIDATx^V]HglFtuv Fhwb.jE/ ujʐ -q.vmaЈCd$[3L)UK"FM4y~ N6x9y9'^RjD^noo/jmm-6k eb0\]]889V>f2$3X䕗 ~,b1ǷzO&7Y%Ð 2P_/=}4Nn*Sn>%Rt3?tH= caeue5* d8ēn%"p7- JJd riSS7L..޶MB5l&T5AU TTAP#Txrv6pxZZAa tG@}~Y}g  !RxtpNML(,1(y;O$LL ęBp+6WxF%[2/%Q}>L"eD6 T껾Rm C6/%w,$~el >1N\2@|ss bs|&|ݾovn! C9rK6\U%;{V% 80QdH$-NGGrg}eHYk2g,H8IWWNxGGl5Wvtcl6Ks"jd2͋=X]]FD゛M]744h/~ԫYIENDB`PNG  IHDRѝIDATxc  dp6IENDB`PNG  IHDR$MIDATxc @BȲSƩyIENDB`PNG  IHDR$MIDATxc 2@CWƂxIENDB`PNG  IHDR /dIDATxcf`@ ? i]IENDB`PNG  IHDR gIDAT BAy{w_PPa߁ ~VkQq@k/{@# l1l64$LPh$$=EIENDB`PNG  IHDR lIDATAVD+j«x^;s0Pp`4ͥX}\ݭ@9nXtn5$)4_1 I2# ̇2qIENDB`PNG  IHDR #2sIDATx^˱0ESTJ¢iЛwoH O#^d$=,(H/# v10 ♁'# -Ň bOKE!#e4!3RAs@1GG|1ptt.bSY9yL,e&&MdyI ~IENDB`PNG  IHDR >IDATxc``ˀY}xIENDB`PNG  IHDR mf4IDATx^A P ?gQ\@zD$h`Kn>w(LʕQ #;8Ac '`NPiƚ-y ;zQXѳJ@)/JH8?BВ7L/ &IENDB`PNG  IHDR >IDATxc@ YNhIENDB`PNG  IHDR mf4IDATx^1 @F7nFP/ `!^8~m10003P‡] z> @t!/=q t_ 7GFzVٔOLl(DB#W,9l.#O*IENDB`PNG  IHDR /dIDATxc@ NK֟IENDB`PNG  IHDR LIDATx^+0E)B;<S ܣ{%Lv,Ë6fI5n]͍^xSV%E6ZIENDB`PNG  IHDR LIDATxc)BW PJ,sXāPa9#0 ' YM" r%D;IENDB`PNG  IHDR #2sRIDATx^͡0 &B/'@ɼݛ\kVCWN$O0-=URھcTn8mʨL̵Wv4tW|IENDB`PNG  IHDR;֕J{IDATxc?٘:@8 chfaa=y[nDžA ulvwgϞ yNIENDB`PNG  IHDR;֕JIDATxc?٘:y3 C=15y6ykljA uRODMlj u5cDj><ۿgJIENDB`PNG  IHDR;֕JxIDATxc?٘:y3 C=14/z޺; y:l6_0Xn@5jV]mm$TCsFl R-mPy~d AoIENDB`PNG  IHDR;֕JIDATxc?٘r@vK;3 ?G̤~y̔ljA u ȚYRO$ u ȚٴROY3V 4ԁԏtlZ)^FO7c@uCU%lUfW_ԡ3sKPy.5$`6<,m is!IENDB`PNG  IHDR;֕JIDATxc?٘:y3 C=15y6yqb"xսЬ&\=n+؝բw``8P9Hf `b! ÅlTE ^CIENDB`PNG  IHDR;֕JwIDATxc?٘:y3 C=14/zn}]I$Rg;U uyTzז9G@ pbgIENDB`PNG  IHDR2IDATx^; 0F?S;8/\+ NRJ;cso?p Ʌ,5:\ :ԴhʾD?hcLFZ+-&+>> :84T.#=90 Mj3pK4e{"C<#NZ'T8GTʄ+q=7nzIENDB`PNG  IHDRR;^jIDATx^ 0E+N]ڥ 3EAp\wGY!p )X#$Iʮ{q4Q߻93m GBr8iYP@EQ'd*TrUU4 ~Uo۶||7eP 03!!t D %KDɑxr8s u}GX.H1L\#H _tiYIENDB`PNG  IHDR2NIDATx10FWg!X@UũO4AGc|pˆ#~VIENDB`PNG  IHDRR;^jIDATxc?E:g@ U 7۳_QnMGϟ?` =*ߑlPʷ$3 5͋y 7$leѣWwAjj 6 b1"HU+IENDB`PNG  IHDRR;^jIDATx^K `-Dm4ʢvjdHoA0 \qDT+ +BaAt(t7 s]09X 0,BX4uX0$AzAiR ,HfJeYqcjfe PL@ePHpHpUK\Л_M9=^coc @\yy q܀4 hܹ ))M$:̛ǐ 2D tiRÌ 30 ~,Ѝ/L$ @s񺗐aa 4(Ni(CC M[<IENDB`PNG  IHDRjx{IDATxb`c@m@0j訡5IA]"WmXwBdsly~,^H7b88Ea 7-(()ߧM,,>uA5kάz$fabL@79{ al"4|w/C9b&"-)#6.ђБj(@GY gIENDB`PNG  IHDRJ'IDATxcP99 ^$*/WIENDB`PNG  IHDRJ'IDATxcP99 ~d` IENDB`PNG  IHDRJ'IDATxc|P99HN]8!ŃGIENDB`PNG  IHDRJ'.IDATcooqƑf0`f`pWaIENDB`PNG  IHDRJ'3IDATxco?,O+x F)=n af`c`pU`IENDB`PNG  IHDRJ'.IDATcto/H9m,lg{ afd`qt8@zFIENDB`PNG  IHDRJ' IDATxcG C8dE +`A}IENDB`PNG  IHDRJ' IDATc  2!ÏARq9IENDB`PNG  IHDRrH IDATcfIENDB`PNG  IHDRrH IDATcg@ BIENDB`PNG  IHDRrH IDATcx-iIENDB`PNG  IHDRW{IDATxc B,5 jIENDB`PNG  IHDRW{IDATc "<4SIENDB`PNG  IHDRW{IDATxc N?B+Tʹ_IENDB`PNG  IHDRآ, IDATc zݭjIENDB`PNG  IHDRآ, IDATcr IENDB`PNG  IHDR!D?jAIDATx^̱ @PFћ$L`VTkkGmMԊ|/E ~+IAIENDB`PNG  IHDR!D?jGIDATxڥ1@@@8J܏=R-72P+DŦ֐`| ֠$u4_#.IENDB`PNG  IHDR!D?j?IDATcX Rn df y9[&IENDB`PNG  IHDR!D?j\*SIENDB`PNG  IHDRJ'IDATxcπ'$οH8,.4IENDB`PNG  IHDRJ'IDATxcπ$οH?8,98>IENDB`PNG  IHDRJ'IDATxcπ'$έHg8$,IENDB`PNG  IHDRJ'(IDATcπ, FaM6l|0of6_z4IENDB`PNG  IHDRJ'-IDATcπ, Fau6 #\0e\`2=p.ZIENDB`PNG  IHDRJ'%IDATxcπFaM6(LMӽ h #"IENDB`PNG  IHDRJ'IDATxcπ'$οqƟp*,A7IENDB`PNG  IHDRJ'IDATxcπ$οq?p3*,?W&1IENDB`PNG  IHDRH'IDATxc,ĿK.bX%Ǫ)iEIENDB`PNG  IHDRH%IDATxc,ĿK.2$رIjvIENDB`PNG  IHDRH&IDATxc|,Ľ{K.'\ uWIENDB`PNG  IHDRHHIDATxc?[W߿?c6o^$  E^o^p!l@,b oBd>W*IENDB`PNG  IHDRHUIDATxc?[W߿cl_>} $ p VԓE_o^p.@,@,`J d3F3ǵIENDB`PNG  IHDRHEIDATxc? OX¹ǛrªP%){OşBp (bM fK`](%a!IENDB`PNG  IHDRH)IDATxct % C$ dž@ +ŠhtWVIENDB`PNG  IHDRH)IDATxct % C$ dž@f`džvW.)IENDB`PNG  IHDRIDATxc?[W߿?c(h˜IENDB`PNG  IHDRIDATc?[W߿c2IENDB`PNG  IHDRIDATxc?޽Ϟ=cxIENDB`PNG  IHDR!MM]IDAT(cXh'[WY .xG,X/Ty wyw[=znq6 ,lpGh"6qKIENDB`PNG  IHDR!MMoIDATŏ @|HYM`(Z&Iej(r|Se%ϏZnfS`T ֈ6z}504K߅ֈ|73/IENDB`PNG  IHDR!MM^IDAT(cXhgϞ߻w]ݏ@ .xG,X,HONa^p}b.;Ā ':ck ;H ,Y;Lb9IENDB`PNG  IHDR!PHY IDATcظq'[WY}P#aBIENDB`PNG  IHDR!PHY$IDATcظq[WDr{MnyIENDB`PNG  IHDR!PHYIDATcظqgϞ߻w]ݏ@@vNtIENDB`PNG  IHDR!MMRIDATx @ Q S$%ie₈\RƁ@@ۍgf>z@03IDATc?6UY¾' Ē(M U F_; >IENDB`PNG  IHDRHAIDATxc?6ĸ%'# WY#]*!!ȈbCE(|IENDB`PNG  IHDRH4IDATxc?6@X¾' Ē( ?_TWg %/A#IENDB`PNG  IHDRH(IDATxc?V[®l߿10?/{lIENDB`PNG  IHDRH(IDATxc?V[®l߿10?/{^{ IENDB`PNG  IHDR iPIDATx^JQm p&7AaQA>,+!  . C%PR*L pf1a in0qYIX$!مӭ{ΖQ1Te#fa>ijU%na\"C ur DטgW]\ y}aˆ=;ңY/ \k6OPA$Gg̴Dgdsjmvȭp tĘ&Ґ>)\pl`5=AQ0r!ve{;bэ 'H#b]IENDB`PNG  IHDR@4=IDATx^Ԙ銝E=#nŨWaPaРH ޔup\ɥ)36ֺt^m@Ȩ$5w4wFƨH5QlkK| p0 f4F"w>nԜU 8V V68S Rw>ZػD_MCQ#7x2e$;po abl ۙ: P%7<,xm!^ӘkcS\ZVKPD55 )߾oUw69Z/• ;"QCGԭŽ ]81;C%b"->GA*fз|uf) x.\ݫLyBWhZ5#o~T%1'd f(R lp7(o|O *]F{4oRAl웇XnfjDz5PbVbqxR/kS+pl **l{Jtج{ܺ}ltn,ƚSUl!TI˜xݭ ŎȯRdAnW6wV+v1GQ.EX'G}:> )*5lQBnp"O[Nf)gVW49#QppX;u@둼tb7#SG1ضmo" |<0Zȋ^Hlͩ28~I^BU~ny؋lXʚRzJ'gՑ=L~gff_G3KbS'˷zCp`v;='q a[r @IǢg7b!1e$ D==$ޠ>}ąsoJboƷ<||ܓ~d7RTƱ \?M GbQÅ`P?-[a*!`E^#;F'nbͅ$ # ԥmp0:k 8vd)Ec^W>!& M?>̤0cE$Qmɓ't8|YlMUM쫻$fF/Ղ 6{`&k:Kn~rl_Ä)!U[q՗Wp3c(vq؍xŚN8H}T\Uy[Y!<{\ǪWΠQi7Y QY[\A.:g 9 P{*f`+- `!}X)3VeɎ=;6c:Z 6i"/V(h @!? xZ0G׮]S$P/k |H_(KBnP 8lI҇iYJIENDB`PNG  IHDR@_XPLTEݚݛޠ᜵ߝߞࡺ♳ݟ᜵ޝߜޡᠺᚲݛޞߚޝߛݟᚴݚޟޞࡹ᜶ޢ⢼⥿夽㤾䥿䦿奾䢻㦿䤽䢼㣼㣽㡻⤾)CIDATx^Ir1SR9N,a[j] 7lm>W.Z4ǽ%s RU4wFhH/_YӺQČ]l&†qa3Af3;c.D@ƘA!0B@ Jiu6W?vٯg0(*| ك/b@ Q"_vKekץ7jmsV滽lFZ8Ku@PP LU#QpEInzu= T&*^I{Z.۷X;ck><7~:>>GhD:j訡 E@IENDB`PNG  IHDR2IDATxڍ0࿠ԋK].vAŋZJ,^7ST$ B ʚL2O6=:.[vYSF&,7ҥ,NQc>rNr:G% l! R1c}u}Zi쒧=>4DS:1 <NˍjޣxPjy< 0i3Ęc/xP u4mv-\ }@IENDB`PNG  IHDR25IDATx^NQ&@60h4!D# Fc@BMx:g3ilf2_]?/ *j!5TPg'|<{=(o (K( %U­fDKPPXdgj#.<; #[ٸTdґWґO4TSEzNzT W&]Ä7ґo] YzHWNT(Ymߍ;js0ݭx0 #rsvs rT993Z8c (Y{J%4;IENDB`PNG  IHDR2IDATx^n0OPœYy?$v#oB"Rcǧ7v<*7O^ #A*$"|0ȳP3 `˳*ņMbLךW:ԢL0<)\,JU[) snm#U!qBjL%?%_m#c )]OE\%/ل/ezS ݘ_2f/*qQQ u>UG>Fx+Fߕ१9 S|IENDB`PNG  IHDR2CIDATx^JaqbiQBjaK٘K7^Z!noA\^0pz%m{ag` q89driwei/WD'n5n(D Ռ}:@+$UHGI&>viaw4x' |BwRGR b(FAIj 5)S7+^mTeu7C^ҕr`<-'e&aJϭRmmGzLZlu4܀sGl64q2p-i ։-$ML1H|')#IENDB`PNG  IHDR2XIDATx^j`ǿH!8XNF .EPl..>/DBDцs.?p ,,"R,|$0Y.moar8XXh‡_@=0+E z>Z(-J\t1ͅȭa W0H 2IG U>fB&&%0݆\ NOD o|x"W3COtM /фjKR6"6ڎra XÃju- XCݚw5qxx,qRHrQ A!QN_7>LeIENDB`PNG  IHDR2IDATxڕ= gͰ3hr)u"ڡP*1F"\DHL(B O[&2C)@PrУГCUZ2/r4Z6?LY@G`6ԂDYBr^7ZvvȖ!+k Z9-lM: y1Uݯjǂ\+o-c#]A]IENDB`PNG  IHDRR;^jwIDATx^JQM wnk,Jm 6VR,\AB0@Al& ps)q}—_ {P*mŠhuK2 8 &VE   ;0?%!3pΥyLNcxT[hw1`Re{Q N] *:^['A`)lnZAWK[%l=U6r+c'sxׯ",:J@qC0w!q ,:JВ M 'WBI ь3Y$q6SKo>MsNS%A(֜_yA:IENDB`PNG  IHDRR;^jIDATxڭT=KBQHڂƢ$2A('!s!Z 4EZ*$lc!(uW{zCؔxxs=^{B \;APBG=ZfV$nj4Oj(af 4x~ö]U4Mh4afT]Wu"t:-n74遗2{\0T霼l6+~BPF"@|>G27\0_P%.r8fZ>хdCMFZ k/2\@Obb5.*܉GxQB 9fȳoo+92R::V GFL#hP!v 3h]?3A|:HIENDB`PNG  IHDRR;^j IDATx^RKkQUbnB.big !!$ PmARiTD d6"IA?Ӗ׌-d\Ւ8u1Oū+S+fuQ_Sh ;>4bO6kspi<?hǓZauq@C^dDLJF_ &y;9y _KןU>"l&, x\(QAuMx0 Q/e {p88K&PHڎ(c!!ueh% Ncq39B{,|T T*-Xگy~eqe! ,bb[8f^Wۂo6z-W?l6 (AFwWf߹DA :Jh4Y)cA NP p8Lh$Sڶw BE"3]T!KKGrrj,٬~dy <\~ժnKLF3x {z V쟞]~pȶm z=r]@c&G}F0oK%8Whp2bgL?&>lP\1wse8Ɨ/vgoڊ?<'\s9ǜeN2orA[ypIENDB`PNG  IHDRR;^jIDATxڥMKQ 5l .IrNA~@A/ZXE-DA I j6ΔLW{`0 ywi"4P5Jw][Jm]_6fuh5kpxK/T"D~5zt&oM@^Fw^2aJu<o=yI3AXPzDۺ8Bc}pЀTNmKp13؞ B,Zw?8ʔVBїt] _f[|8HJ+8|Cq@3/6Q%Ď=y65&*//eZ+,%'ѧRH^zF3xr^05Wʉ \q,pq Y'/1cgb;qSSyLscX-L.kklpIENDB`PNG  IHDRR;^jIDATxڭ.Q-܀, S[H Q;ZaCB"bA#J.Hv3m7HhԜ{424ɜ3s i`|L%.Yhޯ;i~'*E@q9֞-0{$2iFT `\E6N(dlvȞ^LU^qx9`8=u4V,udtM|4&S:Xt+g?\Iq9``θ=L*]ί)HT,ޑ%n }ѹF~vt;BUNn$\UU`9,ȔD<\ۦc`X')sЦ${J~ΐ~j~gضĴ0L;4BJKIENDB`PNG  IHDR2 IDATx^=k@ A"9UZAeů&._A?E4;;6"nB/t>>U?. ׉f7RR8`!PJ#h%#P#_A)pIENDB`PNG  IHDR@sh pHYsod MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3 cHRMz%u0`:o_F(IDATxb?H 00Ao$cPK;@IENDB`PNG  IHDRJ' pHYs  iCCPPhotoshop ICC profilexc``$PPTR~!11 !/?/|pYɕ4\PTp(%8 CzyIA c HRvA cHvH3c OIjE s~AeQfzFcJ~RBpeqIjng^r~QA~QbIj ^<CSU*(A!@riQ Pɰ4c<ƧLL L5ذceffĶ]}&G''+g33W77D)ƼW  t|$((|X$]WtX8VIaɣRҺOdȆ ʝQQU4E9JEIVFu? Y&jX ;?ߠ0X=f+-*,|-lTmEX?wx^V/XkBžV7X[¾D0E F)EǸFŷ$Nܜt6y*S\MFTfU֬=9 | f.y[&QRQX9lZI 7k!}Ͼn¾';Nizb:f=5d޾\ -^qò 4^պZuMon4ԱVmSkP?y=-dϷ_t)זz7<8꧊f|M۟K?|T׼o~ϷU*oQ[ cHRMz%u0`:o_FIDATxbpqL HH -IENDB`PNG  IHDRJ' pHYs  iCCPPhotoshop ICC profilexc``$PPTR~!11 !/?/|pYɕ4\PTp(%8 CzyIA c HRvA cHvH3c OIjE s~AeQfzFcJ~RBpeqIjng^r~QA~QbIj ^<CSU*(A!@riQ Pɰ4c<ƧLL L5ذceffĶ]}&G''+g33W77D)ƼW  t|$((|X$]WtX8VIaɣRҺOdȆ ʝQQU4E9JEIVFu? Y&jX ;?ߠ0X=f+-*,|-lTmEX?wx^V/XkBžV7X[¾D0E F)EǸFŷ$Nܜt6y*S\MFTfU֬=9 | f.y[&QRQX9lZI 7k!}Ͼn¾';Nizb:f=5d޾\ -^qò 4^պZuMon4ԱVmSkP?y=-dϷ_t)זz7<8꧊f|M۟K?|T׼o~ϷU*oQ[ cHRMz%u0`:o_FIDATxbfL HHtEZIENDB`PNG  IHDR pHYsod MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3 cHRMz%u0`:o_FIDATxb```0?:%%/IENDB`PNG  IHDRW{ pHYs  iCCPPhotoshop ICC profilexc``$PPTR~!11 !/?/|pYɕ4\PTp(%8 CzyIA c HRvA cHvH3c OIjE s~AeQfzFcJ~RBpeqIjng^r~QA~QbIj ^<CSU*(A!@riQ Pɰ4c<ƧLL L5ذceffĶ]}&G''+g33W77D)ƼW  t|$((|X$]WtX8VIaɣRҺOdȆ ʝQQU4E9JEIVFu? Y&jX ;?ߠ0X=f+-*,|-lTmEX?wx^V/XkBžV7X[¾D0E F)EǸFŷ$Nܜt6y*S\MFTfU֬=9 | f.y[&QRQX9lZI 7k!}Ͼn¾';Nizb:f=5d޾\ -^qò 4^պZuMon4ԱVmSkP?y=-dϷ_t)זz7<8꧊f|M۟K?|T׼o~ϷU*oQ[ cHRMz%u0`:o_FIDATxb (//\IENDB`PNG  IHDR@aP$ pHYs  iCCPPhotoshop ICC profilexc``$PPTR~!11 !/?/|pYɕ4\PTp(%8 CzyIA c HRvA cHvH3c OIjE s~AeQfzFcJ~RBpeqIjng^r~QA~QbIj ^<CSU*(A!@riQ Pɰ4c<ƧLL L5ذceffĶ]}&G''+g33W77D)ƼW  t|$((|X$]WtX8VIaɣRҺOdȆ ʝQQU4E9JEIVFu? Y&jX ;?ߠ0X=f+-*,|-lTmEX?wx^V/XkBžV7X[¾D0E F)EǸFŷ$Nܜt6y*S\MFTfU֬=9 | f.y[&QRQX9lZI 7k!}Ͼn¾';Nizb:f=5d޾\ -^qò 4^պZuMon4ԱVmSkP?y=-dϷ_t)זz7<8꧊f|M۟K?|T׼o~ϷU*oQ[ cHRMz%u0`:o_F!IDATxbd0fP`g`buHw.={~hIENDB`PNG  IHDRHsRGBgAMA a pHYsodIDATWcpvvv %C doIENDB`PNG  IHDRHsRGBgAMA a pHYsodIDATWcprr2ÆH80  IENDB`PNG  IHDR6c;1IDAT јD(p<] DIҥSENVnTh8IENDB`PNG  IHDR66&LVIDATx^KN1`'wE p_pNK"FVjMD]iڔpPۉ{=vNq_|FAL99P0檱$Y`j.V3TP#P81]5Xzv6明nX4V"{nb4w35׭qFd ~W鱇Pl {{Nӝyy"T`xH ,\&6xOuww#cc2ڕ"-NQ8 P0~|Z?H"U`U Hk&[|0UZ \#[XMytFQBJd6[&,9b$rL9:TaBLPe+̒ "TMC$ j{<C(OF'w)B$e$9$ \*9J)9ϒǔAϔK9,%H*O湌T*OrI'ɜ8/fT !F4IENDB`PNG  IHDR66&LVIDATx^AN@ `@r d*+/שf5Y=OStI/ڴˌ8C#֎ۇU{ppۿŎk-,v["54_0?@T8')L1К$[Dɰ0/Ŕo5`g n p)2ek SS=uc![{U^/V0mȱ/U7KGq2-u^.!xDGh@;Q93 Auʢ9F1'flV)imJ$F3]6Ws;CBIwA6R7So"~$9A:ECsH㛄 ,W:%ǍW,'&"L.oQ)GDlU,BDb,9eTc;SimMHYAoT|"hL[dӴ)`1M1N&řH͹Rď'"RɊei[IENDB`PNG  IHDR9dR8|IDATx^kj1 '"NMhO[%zƚ!3)vlkߎ@zDE| u Uϭ Uu\ l;N% ,}78cv«[yS¡!s&T^kN~vƖ.iib^h 'xN_}9%3)ϭ8JBTxg`WJ -)#)VV=0s;lm|l%g7\ PzL@4Lԁ]m=Α x4>/F+n3"OuI+|RL1y%o.2MJu2;_!7gIENDB`PNG  IHDR9dR8IDATx^mN@QC4+t soLN)w̴Ng d+c}$")6h.Lwq3N3nzlFM768d\mKIgWN.25.=k *;sm,BEkqV⾓sI]w:־?GC+{ |bp_ta|#/ NƤb lR=0f~6$Pp5o<}o ڬGR[p`w42M{\۹.6's]LIENDB`PNG  IHDR9%>IDATx^ˊ1D?4fADDDf,@򞍗#ia٥S9G=Xe:Vfnd #Hnm)_OW[Od|s*5tlK\*IwQR 5$a4VyiVUW1FЗۂ):#`c(ߵq#\WZ;OTỗV O#/fWk؆''/^7y`"Ho*ۊ;@X]I0j PpӔEOsۂ+|X)b fUz#M3ΨYE?vB iXrIENDB`PNG  IHDR FFIDATc`Al cǬmIENDB`PNG  IHDR JΛJIDATx^1 0k-":z D,8f ׺t>&"h[:2dABH=RIENDB`PNG  IHDR JΛJIDATQ @@m㸃S8(mXP(TlTs:]tnDs;#"Ow0JIENDB`PNG  IHDR LIDATxc6W8XLGIENDB`PNG  IHDR LIDATxc@ l LljҰIENDB`PNG  IHDR YOoIDATxc@ T9-Z)IENDB`PNG  IHDR JΛ0IDATxc 0Bi&yad)%M6T&;/T!&)UL!te^nIENDB`PNG  IHDR JΛ0IDATxc X "&F4g`DiE't!Vm\\IENDB`PNG  IHDR SIDATx^mA @ FgEtkԁxzqG1ZFIENDB`