mirror of
				https://github.com/invoiceninja/invoiceninja.git
				synced 2025-11-03 22:07:33 -05:00 
			
		
		
		
	
						commit
						2bda5683cf
					
				@ -6,9 +6,10 @@
 | 
				
			|||||||
<!--
 | 
					<!--
 | 
				
			||||||
<link href="{{ asset('vendor/bootstrap/dist/css/bootstrap.min.css') }}" rel="stylesheet" type="text/css"/> 
 | 
					<link href="{{ asset('vendor/bootstrap/dist/css/bootstrap.min.css') }}" rel="stylesheet" type="text/css"/> 
 | 
				
			||||||
<link href="{{ asset('css/bootstrap.splash.css') }}" rel="stylesheet" type="text/css"/> 
 | 
					<link href="{{ asset('css/bootstrap.splash.css') }}" rel="stylesheet" type="text/css"/> 
 | 
				
			||||||
<link href="{{ asset('css/splash.css') }}" rel="stylesheet" type="text/css"/>    
 | 
					 | 
				
			||||||
-->
 | 
					-->
 | 
				
			||||||
 | 
					<link href="{{ asset('css/splash.css') }}" rel="stylesheet" type="text/css"/>    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
<link href="{{ asset('images/apple-touch-icon-114x114-precomposed.png') }}" rel="apple-touch-icon-precomposed" sizes="114x114">
 | 
					<link href="{{ asset('images/apple-touch-icon-114x114-precomposed.png') }}" rel="apple-touch-icon-precomposed" sizes="114x114">
 | 
				
			||||||
<link href="{{ asset('images/apple-touch-icon-72x72-precomposed.png') }}" rel="apple-touch-icon-precomposed" sizes="72x72">
 | 
					<link href="{{ asset('images/apple-touch-icon-72x72-precomposed.png') }}" rel="apple-touch-icon-precomposed" sizes="72x72">
 | 
				
			||||||
<link href="{{ asset('images/apple-touch-icon-57x57-precomposed.png') }}" rel="apple-touch-icon-precomposed">
 | 
					<link href="{{ asset('images/apple-touch-icon-57x57-precomposed.png') }}" rel="apple-touch-icon-precomposed">
 | 
				
			||||||
 | 
				
			|||||||
@ -2,12 +2,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
@section('content')
 | 
					@section('content')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <style>
 | 
					 | 
				
			||||||
  section.body {
 | 
					 | 
				
			||||||
    background-color: #f8f8f8 !important;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  </style>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  <section class="hero background hero3" data-speed="2" data-type="background">
 | 
					  <section class="hero background hero3" data-speed="2" data-type="background">
 | 
				
			||||||
  <div class="caption-side"></div>
 | 
					  <div class="caption-side"></div>
 | 
				
			||||||
  <div class="container">
 | 
					  <div class="container">
 | 
				
			||||||
@ -21,28 +15,85 @@
 | 
				
			|||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    </section>
 | 
					    </section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 <section class="center" style="background-color:#f8f8f8">
 | 
					 <section class="plans center">
 | 
				
			||||||
  <div class="container">
 | 
					  <div class="container">
 | 
				
			||||||
    <div class="row">
 | 
					    <div class="row">
 | 
				
			||||||
      <div class="col-md-8 col-md-offset-2">
 | 
					      <div class="col-md-8 col-md-offset-2">
 | 
				
			||||||
         <p/>
 | 
					 | 
				
			||||||
        <h2>Go Pro to Unlock Premium Invoice Ninja Features</h2>
 | 
					        <h2>Go Pro to Unlock Premium Invoice Ninja Features</h2>
 | 
				
			||||||
        <p>We believe that the free version of Invoice Ninja is a truly awesome product loaded 
 | 
					        <p>We believe that the free version of Invoice Ninja is a truly awesome product loaded 
 | 
				
			||||||
          with the key features you need to bill your clients electronically. But for those who 
 | 
					          with the key features you need to bill your clients electronically. But for those who 
 | 
				
			||||||
          crave still more Ninja awesomeness, we've unmasked the Invoice Ninja Pro plan, which 
 | 
					          crave still more Ninja awesomeness, we've unmasked the Invoice Ninja Pro plan, which 
 | 
				
			||||||
          offers more versatility, power and customization options for just $50 per year. </p>
 | 
					          offers more versatility, power and customization options for just $50 per year. </p>
 | 
				
			||||||
          <br/> <br/>
 | 
					 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
</section>
 | 
					 <div class="container">
 | 
				
			||||||
 | 
					      <div class="row">
 | 
				
			||||||
 | 
					        <div class="plans-table col-md-9">
 | 
				
			||||||
 | 
					        <div class="col-md-4 desc hide-mobile">
 | 
				
			||||||
 | 
					            <div class="cell"></div>
 | 
				
			||||||
 | 
					            <div class="cell">Number of clients per account</div>
 | 
				
			||||||
 | 
					            <div class="cell">Remove "Created by Invoice Ninja"</div>
 | 
				
			||||||
 | 
					            <div class="cell">Custom invoice fields</div>
 | 
				
			||||||
 | 
					            <div class="cell">Unlimited client invoices</div>
 | 
				
			||||||
 | 
					            <div class="cell">Add your company logo</div>
 | 
				
			||||||
 | 
					            <div class="cell">Live .PDF invoice creation </div>
 | 
				
			||||||
 | 
					            <div class="cell">4 beatiful invoice templates</div>
 | 
				
			||||||
 | 
					            <div class="cell">Accept credit card payments</div>
 | 
				
			||||||
 | 
					            <div class="cell">Multiple currency & language support</div>
 | 
				
			||||||
 | 
					            <div class="cell">Open source platform</div>
 | 
				
			||||||
 | 
					            <div class="cell">Self-hosting available</div>
 | 
				
			||||||
 | 
					            <div class="cell">Customize payment terms</div>
 | 
				
			||||||
 | 
					                        <div class="cell">Pricing</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div style="background-color:#f8f8f8">
 | 
					            
 | 
				
			||||||
  <center><img src="{{ asset('images/pro-plan-chart.png') }}"/></center>
 | 
					            </div>
 | 
				
			||||||
</div>      
 | 
					        <div class="free col-md-4">
 | 
				
			||||||
 | 
					            <div class="cell">Free</div>
 | 
				
			||||||
 | 
					            <div class="cell"><div class="hide-desktop">Number of clients per account</div><span>1000</span></div>
 | 
				
			||||||
 | 
					            <div class="cell"><div class="hide-desktop">Remove "Created by Invoice Ninja"</div><span class="glyphicon glyphicon-remove"></div>
 | 
				
			||||||
 | 
					            <div class="cell"><div class="hide-desktop">Custom invoice fields</div><span class="glyphicon glyphicon-remove"></div>
 | 
				
			||||||
 | 
					            <div class="cell"><div class="hide-desktop">Unlimited client invoices</div><span class="glyphicon glyphicon-ok"></div>
 | 
				
			||||||
 | 
					            <div class="cell"><div class="hide-desktop">Add your company logo</div><span class="glyphicon glyphicon-ok"></div>
 | 
				
			||||||
 | 
					            <div class="cell"><div class="hide-desktop">Live .PDF invoice creation</div><span class="glyphicon glyphicon-ok"></div>
 | 
				
			||||||
 | 
					            <div class="cell"><div class="hide-desktop">4 beatiful invoice templates</div><span class="glyphicon glyphicon-ok"></div>
 | 
				
			||||||
 | 
					            <div class="cell"><div class="hide-desktop">Accept credit card payments</div><span class="glyphicon glyphicon-ok"></div>
 | 
				
			||||||
 | 
					            <div class="cell"><div class="hide-desktop">Multiple currency & language support</div><span class="glyphicon glyphicon-ok"></div>
 | 
				
			||||||
 | 
					            <div class="cell"><div class="hide-desktop">Open source platform</div><span class="glyphicon glyphicon-ok"></div>
 | 
				
			||||||
 | 
					            <div class="cell"><div class="hide-desktop">Self-hosting available</div><span class="glyphicon glyphicon-ok"></div>
 | 
				
			||||||
 | 
					            <div class="cell"><div class="hide-desktop">Customize payment terms</div><span class="glyphicon glyphicon-ok"></div>
 | 
				
			||||||
 | 
					            <div class="cell price"><div class="hide-desktop">Pricing</div><p>Free<span> /Always!</span></p></div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        <div class="pro col-md-4">
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            <div class="cell">Pro Plan<span class="glyphicon glyphicon-star"></div>
 | 
				
			||||||
 | 
					            <div class="cell"><div class="hide-desktop">Number of clients per account</div><span style="color: #2299c0; font-size: 16px;">5000</span></div>
 | 
				
			||||||
 | 
					            <div class="cell"><div class="hide-desktop">Remove "Created by Invoice Ninja"</div><span class="glyphicon glyphicon-ok"></div>
 | 
				
			||||||
 | 
					                <div class="cell"><div class="hide-desktop">Custom invoice fields</div><span class="glyphicon glyphicon-ok"></div>
 | 
				
			||||||
 | 
					                    <div class="cell"><div class="hide-desktop">Unlimited client invoices</div><span class="glyphicon glyphicon-ok"></div>
 | 
				
			||||||
 | 
					              <div class="cell"><div class="hide-desktop">Add your company logo</div><span class="glyphicon glyphicon-ok"></div>
 | 
				
			||||||
 | 
					              <div class="cell"><div class="hide-desktop">Live .PDF invoice creation</div><span class="glyphicon glyphicon-ok"></div>
 | 
				
			||||||
 | 
					              <div class="cell"><div class="hide-desktop">4 beatiful invoice templates</div><span class="glyphicon glyphicon-ok"></div>
 | 
				
			||||||
 | 
					              <div class="cell"><div class="hide-desktop">Accept credit card payments</div><span class="glyphicon glyphicon-ok"></div>
 | 
				
			||||||
 | 
					              <div class="cell"><div class="hide-desktop">Multiple currency & language support</div><span class="glyphicon glyphicon-ok"></div>
 | 
				
			||||||
 | 
					              <div class="cell"><div class="hide-desktop">Open source platform</div><span class="glyphicon glyphicon-ok"></div>
 | 
				
			||||||
 | 
					              <div class="cell"><div class="hide-desktop">Self-hosting available</div><span class="glyphicon glyphicon-ok"></div>
 | 
				
			||||||
 | 
					              <div class="cell"><div class="hide-desktop">Customize payment terms</div><span class="glyphicon glyphicon-ok"></div>
 | 
				
			||||||
 | 
					              <div class="cell price"><div class="hide-desktop">Pricing</div><p>$50<span> /Year</span></p></div>
 | 
				
			||||||
 | 
					              <div class="cell">
 | 
				
			||||||
 | 
					              <a href="#">
 | 
				
			||||||
 | 
					        <div class="cta">
 | 
				
			||||||
 | 
					          <h2 onclick="return getStarted()">GO PRO <span>+</span></h2>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </a>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					     </div>
 | 
				
			||||||
 | 
					                      </div>
 | 
				
			||||||
 | 
					     </div>
 | 
				
			||||||
 | 
					                </section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<section class="upper-footer white-bg">
 | 
				
			||||||
<section style="background-color:#f8f8f8;padding-top:80px;padding-bottom:80px;">
 | 
					 | 
				
			||||||
 <div class="container">
 | 
					 <div class="container">
 | 
				
			||||||
  <div class="row">
 | 
					  <div class="row">
 | 
				
			||||||
    <div class="col-md-3 center-block">
 | 
					    <div class="col-md-3 center-block">
 | 
				
			||||||
 | 
				
			|||||||
@ -282,11 +282,11 @@ section.blue .col-md-6 h1 span {
 | 
				
			|||||||
    text-transform: lowercase;
 | 
					    text-transform: lowercase;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
section.about, section.team {
 | 
					section.about, section.team, section.plans {
 | 
				
			||||||
    padding: 70px 0;
 | 
					    padding: 70px 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
section.about h2, section.team h2 {
 | 
					section.about h2, section.team h2, section.plans h2 {
 | 
				
			||||||
    font-size: 25px;
 | 
					    font-size: 25px;
 | 
				
			||||||
    margin: 0 0 25px;
 | 
					    margin: 0 0 25px;
 | 
				
			||||||
    text-transform: none;
 | 
					    text-transform: none;
 | 
				
			||||||
@ -748,4 +748,68 @@ div.fb_iframe_widget > span {
 | 
				
			|||||||
::-moz-selection {
 | 
					::-moz-selection {
 | 
				
			||||||
    color: #fff;
 | 
					    color: #fff;
 | 
				
			||||||
    background: #2e2b2b;
 | 
					    background: #2e2b2b;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.plans-table {text-align:center; margin: 0 auto; float: none; margin-top: 60px; }
 | 
				
			||||||
 | 
					.plans-table .free, .plans-table .desc { padding: 0; }
 | 
				
			||||||
 | 
					.plans-table .free .cell { padding-right: 15px; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.plans-table .desc .cell { text-align: right; padding-right: 15px; border-left: 1px solid #dfe0e1; font-size: 13px; font-weight: 800; }
 | 
				
			||||||
 | 
					.plans-table .pro .cell { border-left: 1px solid #cccccc; border-right: 1px solid #cccccc;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.plans-table .cell {background-color: #fff; border-top: 1px solid #dfe0e1;padding: 18px 0; font-family: Roboto, sans-serif; height: 60px;}
 | 
				
			||||||
 | 
					.plans-table .cell:nth-child(odd){background-color: #fbfbfb;}
 | 
				
			||||||
 | 
					.plans-table .pro .cell:nth-child(odd){background-color: #f4f4f4;}
 | 
				
			||||||
 | 
					.plans-table .pro {
 | 
				
			||||||
 | 
					    background-color: #2299c0;
 | 
				
			||||||
 | 
					     overflow:hidden;
 | 
				
			||||||
 | 
					    padding: 0;
 | 
				
			||||||
 | 
					-webkit-box-shadow: 0px 0px 15px 0px rgba(0, 5, 5, 0.2);
 | 
				
			||||||
 | 
					-moz-box-shadow:    0px 0px 15px 0px rgba(0, 5, 5, 0.2);
 | 
				
			||||||
 | 
					box-shadow:         0px 0px 15px 0px rgba(0, 5, 5, 0.2);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.plans-table .free .cell:first-child, .plans-table .pro .cell:first-child {color: #fff; text-transform: uppercase; font-size: 24px; font-weight:800; line-height: 60px; padding: 0; position: relative; bottom: -1px; border: none;}
 | 
				
			||||||
 | 
					.plans-table .free .cell:first-child {background-color: #9b9b9b; margin-right: 15px; padding-right: 0;}
 | 
				
			||||||
 | 
					.plans-table .free, .plans-table .desc {border-bottom: 1px solid #dfe0e1;}
 | 
				
			||||||
 | 
					.plans-table .pro .cell:first-child {background-color: #2299c0;}
 | 
				
			||||||
 | 
					.plans-table .pro .cell:last-child {padding: 0; border: none;}
 | 
				
			||||||
 | 
					.plans-table .desc .cell:first-child {background-color: transparent; border: none;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.plans-table .glyphicon {color: #fff; border-radius: 50px; padding: 5px; font-size: 10px;}
 | 
				
			||||||
 | 
					.plans-table .glyphicon-remove {background-color: #da4830;}
 | 
				
			||||||
 | 
					.plans-table .glyphicon-ok {background-color: #35c156;}
 | 
				
			||||||
 | 
					.plans-table .glyphicon-star {border-radius: 0; background-color: #2e2b2b;
 | 
				
			||||||
 | 
					    display: block;  
 | 
				
			||||||
 | 
					    width: 60px;  
 | 
				
			||||||
 | 
					    height: 30px;  
 | 
				
			||||||
 | 
					    position: absolute;  
 | 
				
			||||||
 | 
					    top: -5px;  
 | 
				
			||||||
 | 
					    right: -20px;  
 | 
				
			||||||
 | 
					    -webkit-transform: rotate(45deg);
 | 
				
			||||||
 | 
					    -moz-transform: rotate(45deg);
 | 
				
			||||||
 | 
					    -o-transform: rotate(45deg);
 | 
				
			||||||
 | 
					    transform: rotate(45deg);
 | 
				
			||||||
 | 
					    padding: 13px 0 0 1px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.plans-table .price {padding: 0; }
 | 
				
			||||||
 | 
					.plans-table .free .price p {color: #35c156;}
 | 
				
			||||||
 | 
					.plans-table .pro .price p {color: #2299c0;}
 | 
				
			||||||
 | 
					.plans-table .price p {font-size: 40px; text-transform: uppercase; font-weight: 800; margin: 0; line-height: 55px;}
 | 
				
			||||||
 | 
					.plans-table .price p span {font-size: 16px; text-transform: none; font-weight: 400;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.plans-table a .cta h2 {background: #2299c0; color:#fff; margin: 0;}
 | 
				
			||||||
 | 
					.plans-table a .cta h2 span {background: #1e84a5;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@media screen and (min-width: 769px) {
 | 
				
			||||||
 | 
					   .hide-desktop {display: none;}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					@media screen and (max-width: 769px) {
 | 
				
			||||||
 | 
					   .hide-mobile {display: none;}
 | 
				
			||||||
 | 
					    .plans-table .cell {height: auto; padding: 14px 0; }
 | 
				
			||||||
 | 
					    .plans-table .free .cell { padding-right: 0; }
 | 
				
			||||||
 | 
					    .plans-table .free .cell:first-child {margin-right: 0;}
 | 
				
			||||||
 | 
					       .plans-table .cell div:first-child {margin-bottom: 5px;}
 | 
				
			||||||
 | 
					       .plans-table .cell .cta {margin-bottom: 0 !important;}
 | 
				
			||||||
 | 
					       .plans-table .pro {margin-top: 40px;}
 | 
				
			||||||
 | 
					} 
 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										135
									
								
								public/vendor/pdfjs/extensions/firefox/components/PdfRedirector.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								public/vendor/pdfjs/extensions/firefox/components/PdfRedirector.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,135 @@
 | 
				
			|||||||
 | 
					/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | 
				
			||||||
 | 
					/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 | 
				
			||||||
 | 
					/* Copyright 2012 Mozilla Foundation
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					 * You may obtain a copy of the License at
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					 * See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					 * limitations under the License.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					/* jshint esnext:true */
 | 
				
			||||||
 | 
					/* globals Components, Services, XPCOMUtils, NetUtil, dump */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var EXPORTED_SYMBOLS = ['PdfRedirector'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const Cc = Components.classes;
 | 
				
			||||||
 | 
					const Ci = Components.interfaces;
 | 
				
			||||||
 | 
					const Cr = Components.results;
 | 
				
			||||||
 | 
					const Cu = Components.utils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const PDF_CONTENT_TYPE = 'application/pdf';
 | 
				
			||||||
 | 
					const FIREFOX_ID = '{ec8030f7-c20a-464f-9b0e-13a3a9e97384}';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Cu.import('resource://gre/modules/XPCOMUtils.jsm');
 | 
				
			||||||
 | 
					Cu.import('resource://gre/modules/Services.jsm');
 | 
				
			||||||
 | 
					Cu.import('resource://gre/modules/NetUtil.jsm');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function getDOMWindow(aChannel) {
 | 
				
			||||||
 | 
					  var requestor = aChannel.notificationCallbacks ?
 | 
				
			||||||
 | 
					                  aChannel.notificationCallbacks :
 | 
				
			||||||
 | 
					                  aChannel.loadGroup.notificationCallbacks;
 | 
				
			||||||
 | 
					  var win = requestor.getInterface(Components.interfaces.nsIDOMWindow);
 | 
				
			||||||
 | 
					  return win;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function getObjectUrl(window) {
 | 
				
			||||||
 | 
					  // PlayPreview overlay "belongs" to the embed/object tag and consists of DIV
 | 
				
			||||||
 | 
					  // and IFRAME. Starting from IFRAME and looking for first object tag.
 | 
				
			||||||
 | 
					  var element = window.frameElement, containerElement;
 | 
				
			||||||
 | 
					  if (!element) {
 | 
				
			||||||
 | 
					    return null; // iframe tag
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  var tagName = element.nodeName;
 | 
				
			||||||
 | 
					  while (tagName !== 'EMBED' && tagName !== 'OBJECT') {
 | 
				
			||||||
 | 
					    containerElement = element;
 | 
				
			||||||
 | 
					    element = element.parentNode;
 | 
				
			||||||
 | 
					    if (!element) {
 | 
				
			||||||
 | 
					      return null; // object tag was not found
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    tagName = element.nodeName;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Checking if overlay is a proper PlayPreview overlay.
 | 
				
			||||||
 | 
					  for (var i = 0; i < element.children.length; i++) {
 | 
				
			||||||
 | 
					    if (element.children[i] === containerElement) {
 | 
				
			||||||
 | 
					      return null; // invalid plugin element overlay
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return element.srcURI.spec;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function PdfRedirector() {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PdfRedirector.prototype = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // properties required for XPCOM registration:
 | 
				
			||||||
 | 
					  classID: Components.ID('{8cbfd8d0-2042-4976-b3ef-d9dee1efb975}'),
 | 
				
			||||||
 | 
					  classDescription: 'pdf.js Redirector',
 | 
				
			||||||
 | 
					  contractID:
 | 
				
			||||||
 | 
					    '@mozilla.org/streamconv;1?from=application/x-moz-playpreview-pdfjs&to=*/*',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  QueryInterface: XPCOMUtils.generateQI([
 | 
				
			||||||
 | 
					      Ci.nsIStreamConverter,
 | 
				
			||||||
 | 
					      Ci.nsIStreamListener,
 | 
				
			||||||
 | 
					      Ci.nsIRequestObserver
 | 
				
			||||||
 | 
					  ]),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // nsIStreamConverter::convert
 | 
				
			||||||
 | 
					  convert: function(aFromStream, aFromType, aToType, aCtxt) {
 | 
				
			||||||
 | 
					    throw Cr.NS_ERROR_NOT_IMPLEMENTED;
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // nsIStreamConverter::asyncConvertData
 | 
				
			||||||
 | 
					  asyncConvertData: function(aFromType, aToType, aListener, aCtxt) {
 | 
				
			||||||
 | 
					    // Store the listener passed to us
 | 
				
			||||||
 | 
					    this.listener = aListener;
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // nsIStreamListener::onDataAvailable
 | 
				
			||||||
 | 
					  onDataAvailable: function(aRequest, aContext, aInputStream, aOffset, aCount) {
 | 
				
			||||||
 | 
					    // Do nothing since all the data loading is handled by the viewer.
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // nsIRequestObserver::onStartRequest
 | 
				
			||||||
 | 
					  onStartRequest: function(aRequest, aContext) {
 | 
				
			||||||
 | 
					    // Setup the request so we can use it below.
 | 
				
			||||||
 | 
					    aRequest.QueryInterface(Ci.nsIChannel);
 | 
				
			||||||
 | 
					    // Cancel the request so the viewer can handle it.
 | 
				
			||||||
 | 
					    aRequest.cancel(Cr.NS_BINDING_ABORTED);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var domWindow = getDOMWindow(aRequest);
 | 
				
			||||||
 | 
					    var pdfUrl = getObjectUrl(domWindow);
 | 
				
			||||||
 | 
					    if (!pdfUrl) {
 | 
				
			||||||
 | 
					      Services.console.logStringMessage(
 | 
				
			||||||
 | 
					        'PdfRedirector.js: PDF location is not specified for OBJECT/EMBED tag');
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Create a new channel that is viewer loaded as a resource.
 | 
				
			||||||
 | 
					    var ioService = Services.io;
 | 
				
			||||||
 | 
					    var channel = ioService.newChannel(pdfUrl, null, null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    channel.loadGroup = aRequest.loadGroup;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    channel.asyncOpen(this.listener, aContext);
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // nsIRequestObserver::onStopRequest
 | 
				
			||||||
 | 
					  onStopRequest: function(aRequest, aContext, aStatusCode) {
 | 
				
			||||||
 | 
					    // Do nothing
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var NSGetFactory = XPCOMUtils.generateNSGetFactory([PdfRedirector]);
 | 
				
			||||||
							
								
								
									
										963
									
								
								public/vendor/pdfjs/extensions/firefox/components/PdfStreamConverter.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										963
									
								
								public/vendor/pdfjs/extensions/firefox/components/PdfStreamConverter.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,963 @@
 | 
				
			|||||||
 | 
					/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | 
				
			||||||
 | 
					/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
 | 
				
			||||||
 | 
					/* Copyright 2012 Mozilla Foundation
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					 * you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					 * You may obtain a copy of the License at
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					 * See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					 * limitations under the License.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					/* jshint esnext:true */
 | 
				
			||||||
 | 
					/* globals Components, Services, XPCOMUtils, NetUtil, PrivateBrowsingUtils,
 | 
				
			||||||
 | 
					           dump, NetworkManager, PdfJsTelemetry, DEFAULT_PREFERENCES */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					'use strict';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var EXPORTED_SYMBOLS = ['PdfStreamConverter'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const Cc = Components.classes;
 | 
				
			||||||
 | 
					const Ci = Components.interfaces;
 | 
				
			||||||
 | 
					const Cr = Components.results;
 | 
				
			||||||
 | 
					const Cu = Components.utils;
 | 
				
			||||||
 | 
					// True only if this is the version of pdf.js that is included with firefox.
 | 
				
			||||||
 | 
					const MOZ_CENTRAL = JSON.parse('PDFJSSCRIPT_MOZ_CENTRAL');
 | 
				
			||||||
 | 
					const PDFJS_EVENT_ID = 'pdf.js.message';
 | 
				
			||||||
 | 
					const PDF_CONTENT_TYPE = 'application/pdf';
 | 
				
			||||||
 | 
					const PREF_PREFIX = 'PDFJSSCRIPT_PREF_PREFIX';
 | 
				
			||||||
 | 
					const PDF_VIEWER_WEB_PAGE = 'resource://pdf.js/web/viewer.html';
 | 
				
			||||||
 | 
					const MAX_DATABASE_LENGTH = 4096;
 | 
				
			||||||
 | 
					const MAX_STRING_PREF_LENGTH = 4096;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Cu.import('resource://gre/modules/XPCOMUtils.jsm');
 | 
				
			||||||
 | 
					Cu.import('resource://gre/modules/Services.jsm');
 | 
				
			||||||
 | 
					Cu.import('resource://gre/modules/NetUtil.jsm');
 | 
				
			||||||
 | 
					Cu.import('resource://pdf.js/network.js');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Load the default preferences.
 | 
				
			||||||
 | 
					Cu.import('resource://pdf.js/default_preferences.js');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					XPCOMUtils.defineLazyModuleGetter(this, 'PrivateBrowsingUtils',
 | 
				
			||||||
 | 
					  'resource://gre/modules/PrivateBrowsingUtils.jsm');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					XPCOMUtils.defineLazyModuleGetter(this, 'PdfJsTelemetry',
 | 
				
			||||||
 | 
					  'resource://pdf.js/PdfJsTelemetry.jsm');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var Svc = {};
 | 
				
			||||||
 | 
					XPCOMUtils.defineLazyServiceGetter(Svc, 'mime',
 | 
				
			||||||
 | 
					                                   '@mozilla.org/mime;1',
 | 
				
			||||||
 | 
					                                   'nsIMIMEService');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function getChromeWindow(domWindow) {
 | 
				
			||||||
 | 
					  var containingBrowser = domWindow.QueryInterface(Ci.nsIInterfaceRequestor)
 | 
				
			||||||
 | 
					                                   .getInterface(Ci.nsIWebNavigation)
 | 
				
			||||||
 | 
					                                   .QueryInterface(Ci.nsIDocShell)
 | 
				
			||||||
 | 
					                                   .chromeEventHandler;
 | 
				
			||||||
 | 
					  return containingBrowser.ownerDocument.defaultView;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function setBoolPref(pref, value) {
 | 
				
			||||||
 | 
					  Services.prefs.setBoolPref(pref, value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function getBoolPref(pref, def) {
 | 
				
			||||||
 | 
					  try {
 | 
				
			||||||
 | 
					    return Services.prefs.getBoolPref(pref);
 | 
				
			||||||
 | 
					  } catch (ex) {
 | 
				
			||||||
 | 
					    return def;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function setIntPref(pref, value) {
 | 
				
			||||||
 | 
					  Services.prefs.setIntPref(pref, value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function getIntPref(pref, def) {
 | 
				
			||||||
 | 
					  try {
 | 
				
			||||||
 | 
					    return Services.prefs.getIntPref(pref);
 | 
				
			||||||
 | 
					  } catch (ex) {
 | 
				
			||||||
 | 
					    return def;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function setStringPref(pref, value) {
 | 
				
			||||||
 | 
					  var str = Cc['@mozilla.org/supports-string;1']
 | 
				
			||||||
 | 
					              .createInstance(Ci.nsISupportsString);
 | 
				
			||||||
 | 
					  str.data = value;
 | 
				
			||||||
 | 
					  Services.prefs.setComplexValue(pref, Ci.nsISupportsString, str);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function getStringPref(pref, def) {
 | 
				
			||||||
 | 
					  try {
 | 
				
			||||||
 | 
					    return Services.prefs.getComplexValue(pref, Ci.nsISupportsString).data;
 | 
				
			||||||
 | 
					  } catch (ex) {
 | 
				
			||||||
 | 
					    return def;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function log(aMsg) {
 | 
				
			||||||
 | 
					  if (!getBoolPref(PREF_PREFIX + '.pdfBugEnabled', false))
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  var msg = 'PdfStreamConverter.js: ' + (aMsg.join ? aMsg.join('') : aMsg);
 | 
				
			||||||
 | 
					  Services.console.logStringMessage(msg);
 | 
				
			||||||
 | 
					  dump(msg + '\n');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function getDOMWindow(aChannel) {
 | 
				
			||||||
 | 
					  var requestor = aChannel.notificationCallbacks ?
 | 
				
			||||||
 | 
					                  aChannel.notificationCallbacks :
 | 
				
			||||||
 | 
					                  aChannel.loadGroup.notificationCallbacks;
 | 
				
			||||||
 | 
					  var win = requestor.getInterface(Components.interfaces.nsIDOMWindow);
 | 
				
			||||||
 | 
					  return win;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function getLocalizedStrings(path) {
 | 
				
			||||||
 | 
					  var stringBundle = Cc['@mozilla.org/intl/stringbundle;1'].
 | 
				
			||||||
 | 
					      getService(Ci.nsIStringBundleService).
 | 
				
			||||||
 | 
					      createBundle('chrome://pdf.js/locale/' + path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  var map = {};
 | 
				
			||||||
 | 
					  var enumerator = stringBundle.getSimpleEnumeration();
 | 
				
			||||||
 | 
					  while (enumerator.hasMoreElements()) {
 | 
				
			||||||
 | 
					    var string = enumerator.getNext().QueryInterface(Ci.nsIPropertyElement);
 | 
				
			||||||
 | 
					    var key = string.key, property = 'textContent';
 | 
				
			||||||
 | 
					    var i = key.lastIndexOf('.');
 | 
				
			||||||
 | 
					    if (i >= 0) {
 | 
				
			||||||
 | 
					      property = key.substring(i + 1);
 | 
				
			||||||
 | 
					      key = key.substring(0, i);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (!(key in map))
 | 
				
			||||||
 | 
					      map[key] = {};
 | 
				
			||||||
 | 
					    map[key][property] = string.value;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return map;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					function getLocalizedString(strings, id, property) {
 | 
				
			||||||
 | 
					  property = property || 'textContent';
 | 
				
			||||||
 | 
					  if (id in strings)
 | 
				
			||||||
 | 
					    return strings[id][property];
 | 
				
			||||||
 | 
					  return id;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// PDF data storage
 | 
				
			||||||
 | 
					function PdfDataListener(length) {
 | 
				
			||||||
 | 
					  this.length = length; // less than 0, if length is unknown
 | 
				
			||||||
 | 
					  this.data = new Uint8Array(length >= 0 ? length : 0x10000);
 | 
				
			||||||
 | 
					  this.loaded = 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PdfDataListener.prototype = {
 | 
				
			||||||
 | 
					  append: function PdfDataListener_append(chunk) {
 | 
				
			||||||
 | 
					    var willBeLoaded = this.loaded + chunk.length;
 | 
				
			||||||
 | 
					    if (this.length >= 0 && this.length < willBeLoaded) {
 | 
				
			||||||
 | 
					      this.length = -1; // reset the length, server is giving incorrect one
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (this.length < 0 && this.data.length < willBeLoaded) {
 | 
				
			||||||
 | 
					      // data length is unknown and new chunk will not fit in the existing
 | 
				
			||||||
 | 
					      // buffer, resizing the buffer by doubling the its last length
 | 
				
			||||||
 | 
					      var newLength = this.data.length;
 | 
				
			||||||
 | 
					      for (; newLength < willBeLoaded; newLength *= 2) {}
 | 
				
			||||||
 | 
					      var newData = new Uint8Array(newLength);
 | 
				
			||||||
 | 
					      newData.set(this.data);
 | 
				
			||||||
 | 
					      this.data = newData;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    this.data.set(chunk, this.loaded);
 | 
				
			||||||
 | 
					    this.loaded = willBeLoaded;
 | 
				
			||||||
 | 
					    this.onprogress(this.loaded, this.length >= 0 ? this.length : void(0));
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  getData: function PdfDataListener_getData() {
 | 
				
			||||||
 | 
					    var data = this.data;
 | 
				
			||||||
 | 
					    if (this.loaded != data.length)
 | 
				
			||||||
 | 
					      data = data.subarray(0, this.loaded);
 | 
				
			||||||
 | 
					    delete this.data; // releasing temporary storage
 | 
				
			||||||
 | 
					    return data;
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  finish: function PdfDataListener_finish() {
 | 
				
			||||||
 | 
					    this.isDataReady = true;
 | 
				
			||||||
 | 
					    if (this.oncompleteCallback) {
 | 
				
			||||||
 | 
					      this.oncompleteCallback(this.getData());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  error: function PdfDataListener_error(errorCode) {
 | 
				
			||||||
 | 
					    this.errorCode = errorCode;
 | 
				
			||||||
 | 
					    if (this.oncompleteCallback) {
 | 
				
			||||||
 | 
					      this.oncompleteCallback(null, errorCode);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  onprogress: function() {},
 | 
				
			||||||
 | 
					  get oncomplete() {
 | 
				
			||||||
 | 
					    return this.oncompleteCallback;
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  set oncomplete(value) {
 | 
				
			||||||
 | 
					    this.oncompleteCallback = value;
 | 
				
			||||||
 | 
					    if (this.isDataReady) {
 | 
				
			||||||
 | 
					      value(this.getData());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (this.errorCode) {
 | 
				
			||||||
 | 
					      value(null, this.errorCode);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// All the priviledged actions.
 | 
				
			||||||
 | 
					function ChromeActions(domWindow, contentDispositionFilename) {
 | 
				
			||||||
 | 
					  this.domWindow = domWindow;
 | 
				
			||||||
 | 
					  this.contentDispositionFilename = contentDispositionFilename;
 | 
				
			||||||
 | 
					  this.telemetryState = {
 | 
				
			||||||
 | 
					    documentInfo: false,
 | 
				
			||||||
 | 
					    firstPageInfo: false,
 | 
				
			||||||
 | 
					    streamTypesUsed: [],
 | 
				
			||||||
 | 
					    startAt: Date.now()
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ChromeActions.prototype = {
 | 
				
			||||||
 | 
					  isInPrivateBrowsing: function() {
 | 
				
			||||||
 | 
					    return PrivateBrowsingUtils.isWindowPrivate(this.domWindow);
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  download: function(data, sendResponse) {
 | 
				
			||||||
 | 
					    var self = this;
 | 
				
			||||||
 | 
					    var originalUrl = data.originalUrl;
 | 
				
			||||||
 | 
					    // The data may not be downloaded so we need just retry getting the pdf with
 | 
				
			||||||
 | 
					    // the original url.
 | 
				
			||||||
 | 
					    var originalUri = NetUtil.newURI(data.originalUrl);
 | 
				
			||||||
 | 
					    var filename = data.filename;
 | 
				
			||||||
 | 
					    if (typeof filename !== 'string' || !/\.pdf$/i.test(filename)) {
 | 
				
			||||||
 | 
					      filename = 'document.pdf';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    var blobUri = data.blobUrl ? NetUtil.newURI(data.blobUrl) : originalUri;
 | 
				
			||||||
 | 
					    var extHelperAppSvc =
 | 
				
			||||||
 | 
					          Cc['@mozilla.org/uriloader/external-helper-app-service;1'].
 | 
				
			||||||
 | 
					             getService(Ci.nsIExternalHelperAppService);
 | 
				
			||||||
 | 
					    var frontWindow = Cc['@mozilla.org/embedcomp/window-watcher;1'].
 | 
				
			||||||
 | 
					                         getService(Ci.nsIWindowWatcher).activeWindow;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var docIsPrivate = this.isInPrivateBrowsing();
 | 
				
			||||||
 | 
					    var netChannel = NetUtil.newChannel(blobUri);
 | 
				
			||||||
 | 
					    if ('nsIPrivateBrowsingChannel' in Ci &&
 | 
				
			||||||
 | 
					        netChannel instanceof Ci.nsIPrivateBrowsingChannel) {
 | 
				
			||||||
 | 
					      netChannel.setPrivate(docIsPrivate);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    NetUtil.asyncFetch(netChannel, function(aInputStream, aResult) {
 | 
				
			||||||
 | 
					      if (!Components.isSuccessCode(aResult)) {
 | 
				
			||||||
 | 
					        if (sendResponse)
 | 
				
			||||||
 | 
					          sendResponse(true);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      // Create a nsIInputStreamChannel so we can set the url on the channel
 | 
				
			||||||
 | 
					      // so the filename will be correct.
 | 
				
			||||||
 | 
					      var channel = Cc['@mozilla.org/network/input-stream-channel;1'].
 | 
				
			||||||
 | 
					                       createInstance(Ci.nsIInputStreamChannel);
 | 
				
			||||||
 | 
					      channel.QueryInterface(Ci.nsIChannel);
 | 
				
			||||||
 | 
					      try {
 | 
				
			||||||
 | 
					        // contentDisposition/contentDispositionFilename is readonly before FF18
 | 
				
			||||||
 | 
					        channel.contentDisposition = Ci.nsIChannel.DISPOSITION_ATTACHMENT;
 | 
				
			||||||
 | 
					        if (self.contentDispositionFilename) {
 | 
				
			||||||
 | 
					          channel.contentDispositionFilename = self.contentDispositionFilename;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          channel.contentDispositionFilename = filename;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      } catch (e) {}
 | 
				
			||||||
 | 
					      channel.setURI(originalUri);
 | 
				
			||||||
 | 
					      channel.contentStream = aInputStream;
 | 
				
			||||||
 | 
					      if ('nsIPrivateBrowsingChannel' in Ci &&
 | 
				
			||||||
 | 
					          channel instanceof Ci.nsIPrivateBrowsingChannel) {
 | 
				
			||||||
 | 
					        channel.setPrivate(docIsPrivate);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      var listener = {
 | 
				
			||||||
 | 
					        extListener: null,
 | 
				
			||||||
 | 
					        onStartRequest: function(aRequest, aContext) {
 | 
				
			||||||
 | 
					          this.extListener = extHelperAppSvc.doContent('application/pdf',
 | 
				
			||||||
 | 
					                                aRequest, frontWindow, false);
 | 
				
			||||||
 | 
					          this.extListener.onStartRequest(aRequest, aContext);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        onStopRequest: function(aRequest, aContext, aStatusCode) {
 | 
				
			||||||
 | 
					          if (this.extListener)
 | 
				
			||||||
 | 
					            this.extListener.onStopRequest(aRequest, aContext, aStatusCode);
 | 
				
			||||||
 | 
					          // Notify the content code we're done downloading.
 | 
				
			||||||
 | 
					          if (sendResponse)
 | 
				
			||||||
 | 
					            sendResponse(false);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        onDataAvailable: function(aRequest, aContext, aInputStream, aOffset,
 | 
				
			||||||
 | 
					                                  aCount) {
 | 
				
			||||||
 | 
					          this.extListener.onDataAvailable(aRequest, aContext, aInputStream,
 | 
				
			||||||
 | 
					                                           aOffset, aCount);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      channel.asyncOpen(listener, null);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  setDatabase: function(data) {
 | 
				
			||||||
 | 
					    if (this.isInPrivateBrowsing())
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    // Protect against something sending tons of data to setDatabase.
 | 
				
			||||||
 | 
					    if (data.length > MAX_DATABASE_LENGTH)
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    setStringPref(PREF_PREFIX + '.database', data);
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  getDatabase: function() {
 | 
				
			||||||
 | 
					    if (this.isInPrivateBrowsing())
 | 
				
			||||||
 | 
					      return '{}';
 | 
				
			||||||
 | 
					    return getStringPref(PREF_PREFIX + '.database', '{}');
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  getLocale: function() {
 | 
				
			||||||
 | 
					    return getStringPref('general.useragent.locale', 'en-US');
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  getStrings: function(data) {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      // Lazy initialization of localizedStrings
 | 
				
			||||||
 | 
					      if (!('localizedStrings' in this))
 | 
				
			||||||
 | 
					        this.localizedStrings = getLocalizedStrings('viewer.properties');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      var result = this.localizedStrings[data];
 | 
				
			||||||
 | 
					      return JSON.stringify(result || null);
 | 
				
			||||||
 | 
					    } catch (e) {
 | 
				
			||||||
 | 
					      log('Unable to retrive localized strings: ' + e);
 | 
				
			||||||
 | 
					      return 'null';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  pdfBugEnabled: function() {
 | 
				
			||||||
 | 
					    return getBoolPref(PREF_PREFIX + '.pdfBugEnabled', false);
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  supportsIntegratedFind: function() {
 | 
				
			||||||
 | 
					    // Integrated find is only supported when we're not in a frame and when the
 | 
				
			||||||
 | 
					    // new find events code exists.
 | 
				
			||||||
 | 
					    return this.domWindow.frameElement === null &&
 | 
				
			||||||
 | 
					           getChromeWindow(this.domWindow).gFindBar &&
 | 
				
			||||||
 | 
					           'updateControlState' in getChromeWindow(this.domWindow).gFindBar;
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  supportsDocumentFonts: function() {
 | 
				
			||||||
 | 
					    var prefBrowser = getIntPref('browser.display.use_document_fonts', 1);
 | 
				
			||||||
 | 
					    var prefGfx = getBoolPref('gfx.downloadable_fonts.enabled', true);
 | 
				
			||||||
 | 
					    return (!!prefBrowser && prefGfx);
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  supportsDocumentColors: function() {
 | 
				
			||||||
 | 
					    return getBoolPref('browser.display.use_document_colors', true);
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  reportTelemetry: function (data) {
 | 
				
			||||||
 | 
					    var probeInfo = JSON.parse(data);
 | 
				
			||||||
 | 
					    switch (probeInfo.type) {
 | 
				
			||||||
 | 
					      case 'documentInfo':
 | 
				
			||||||
 | 
					        if (!this.telemetryState.documentInfo) {
 | 
				
			||||||
 | 
					          PdfJsTelemetry.onDocumentVersion(probeInfo.version | 0);
 | 
				
			||||||
 | 
					          PdfJsTelemetry.onDocumentGenerator(probeInfo.generator | 0);
 | 
				
			||||||
 | 
					          if (probeInfo.formType) {
 | 
				
			||||||
 | 
					            PdfJsTelemetry.onForm(probeInfo.formType === 'acroform');
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          this.telemetryState.documentInfo = true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      case 'pageInfo':
 | 
				
			||||||
 | 
					        if (!this.telemetryState.firstPageInfo) {
 | 
				
			||||||
 | 
					          var duration = Date.now() - this.telemetryState.startAt;
 | 
				
			||||||
 | 
					          PdfJsTelemetry.onTimeToView(duration);
 | 
				
			||||||
 | 
					          this.telemetryState.firstPageInfo = true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      case 'streamInfo':
 | 
				
			||||||
 | 
					        if (!Array.isArray(probeInfo.streamTypes)) {
 | 
				
			||||||
 | 
					          break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        for (var i = 0; i < probeInfo.streamTypes.length; i++) {
 | 
				
			||||||
 | 
					          var streamTypeId = probeInfo.streamTypes[i] | 0;
 | 
				
			||||||
 | 
					          if (streamTypeId >= 0 && streamTypeId < 10 &&
 | 
				
			||||||
 | 
					              !this.telemetryState.streamTypesUsed[streamTypeId]) {
 | 
				
			||||||
 | 
					            PdfJsTelemetry.onStreamType(streamTypeId);
 | 
				
			||||||
 | 
					            this.telemetryState.streamTypesUsed[streamTypeId] = true;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  fallback: function(args, sendResponse) {
 | 
				
			||||||
 | 
					    var featureId = args.featureId;
 | 
				
			||||||
 | 
					    var url = args.url;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var self = this;
 | 
				
			||||||
 | 
					    var domWindow = this.domWindow;
 | 
				
			||||||
 | 
					    var strings = getLocalizedStrings('chrome.properties');
 | 
				
			||||||
 | 
					    var message;
 | 
				
			||||||
 | 
					    if (featureId === 'forms') {
 | 
				
			||||||
 | 
					      message = getLocalizedString(strings, 'unsupported_feature_forms');
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      message = getLocalizedString(strings, 'unsupported_feature');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    PdfJsTelemetry.onFallback();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var notificationBox = null;
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      // Based on MDN's "Working with windows in chrome code"
 | 
				
			||||||
 | 
					      var mainWindow = domWindow
 | 
				
			||||||
 | 
					        .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
 | 
				
			||||||
 | 
					        .getInterface(Components.interfaces.nsIWebNavigation)
 | 
				
			||||||
 | 
					        .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
 | 
				
			||||||
 | 
					        .rootTreeItem
 | 
				
			||||||
 | 
					        .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
 | 
				
			||||||
 | 
					        .getInterface(Components.interfaces.nsIDOMWindow);
 | 
				
			||||||
 | 
					      var browser = mainWindow.gBrowser
 | 
				
			||||||
 | 
					                              .getBrowserForDocument(domWindow.top.document);
 | 
				
			||||||
 | 
					      notificationBox = mainWindow.gBrowser.getNotificationBox(browser);
 | 
				
			||||||
 | 
					    } catch (e) {
 | 
				
			||||||
 | 
					      log('Unable to get a notification box for the fallback message');
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Flag so we don't call the response callback twice, since if the user
 | 
				
			||||||
 | 
					    // clicks open with different viewer both the button callback and
 | 
				
			||||||
 | 
					    // eventCallback will be called.
 | 
				
			||||||
 | 
					    var sentResponse = false;
 | 
				
			||||||
 | 
					    var buttons = [{
 | 
				
			||||||
 | 
					      label: getLocalizedString(strings, 'open_with_different_viewer'),
 | 
				
			||||||
 | 
					      accessKey: getLocalizedString(strings, 'open_with_different_viewer',
 | 
				
			||||||
 | 
					                                    'accessKey'),
 | 
				
			||||||
 | 
					      callback: function() {
 | 
				
			||||||
 | 
					        sentResponse = true;
 | 
				
			||||||
 | 
					        sendResponse(true);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }];
 | 
				
			||||||
 | 
					    notificationBox.appendNotification(message, 'pdfjs-fallback', null,
 | 
				
			||||||
 | 
					                                       notificationBox.PRIORITY_INFO_LOW,
 | 
				
			||||||
 | 
					                                       buttons,
 | 
				
			||||||
 | 
					                                       function eventsCallback(eventType) {
 | 
				
			||||||
 | 
					      // Currently there is only one event "removed" but if there are any other
 | 
				
			||||||
 | 
					      // added in the future we still only care about removed at the moment.
 | 
				
			||||||
 | 
					      if (eventType !== 'removed')
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					      // Don't send a response again if we already responded when the button was
 | 
				
			||||||
 | 
					      // clicked.
 | 
				
			||||||
 | 
					      if (!sentResponse)
 | 
				
			||||||
 | 
					        sendResponse(false);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  updateFindControlState: function(data) {
 | 
				
			||||||
 | 
					    if (!this.supportsIntegratedFind())
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    // Verify what we're sending to the findbar.
 | 
				
			||||||
 | 
					    var result = data.result;
 | 
				
			||||||
 | 
					    var findPrevious = data.findPrevious;
 | 
				
			||||||
 | 
					    var findPreviousType = typeof findPrevious;
 | 
				
			||||||
 | 
					    if ((typeof result !== 'number' || result < 0 || result > 3) ||
 | 
				
			||||||
 | 
					        (findPreviousType !== 'undefined' && findPreviousType !== 'boolean')) {
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    getChromeWindow(this.domWindow).gFindBar
 | 
				
			||||||
 | 
					                                   .updateControlState(result, findPrevious);
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  setPreferences: function(prefs) {
 | 
				
			||||||
 | 
					    var prefValue, defaultValue, prefName, prefType, defaultType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (var key in DEFAULT_PREFERENCES) {
 | 
				
			||||||
 | 
					      prefValue = prefs[key];
 | 
				
			||||||
 | 
					      defaultValue = DEFAULT_PREFERENCES[key];
 | 
				
			||||||
 | 
					      prefName = (PREF_PREFIX + '.' + key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (prefValue === undefined || prefValue === defaultValue) {
 | 
				
			||||||
 | 
					        Services.prefs.clearUserPref(prefName);
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        prefType = typeof prefValue;
 | 
				
			||||||
 | 
					        defaultType = typeof defaultValue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (prefType !== defaultType) {
 | 
				
			||||||
 | 
					          continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        switch (defaultType) {
 | 
				
			||||||
 | 
					          case 'boolean':
 | 
				
			||||||
 | 
					            setBoolPref(prefName, prefValue);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					          case 'number':
 | 
				
			||||||
 | 
					            setIntPref(prefName, prefValue);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					          case 'string':
 | 
				
			||||||
 | 
					            // Protect against adding arbitrarily long strings in about:config.
 | 
				
			||||||
 | 
					            if (prefValue.length <= MAX_STRING_PREF_LENGTH) {
 | 
				
			||||||
 | 
					              setStringPref(prefName, prefValue);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  getPreferences: function() {
 | 
				
			||||||
 | 
					    var currentPrefs = {};
 | 
				
			||||||
 | 
					    var defaultValue, prefName;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (var key in DEFAULT_PREFERENCES) {
 | 
				
			||||||
 | 
					      defaultValue = DEFAULT_PREFERENCES[key];
 | 
				
			||||||
 | 
					      prefName = (PREF_PREFIX + '.' + key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      switch (typeof defaultValue) {
 | 
				
			||||||
 | 
					        case 'boolean':
 | 
				
			||||||
 | 
					          currentPrefs[key] = getBoolPref(prefName, defaultValue);
 | 
				
			||||||
 | 
					          break;
 | 
				
			||||||
 | 
					        case 'number':
 | 
				
			||||||
 | 
					          currentPrefs[key] = getIntPref(prefName, defaultValue);
 | 
				
			||||||
 | 
					          break;
 | 
				
			||||||
 | 
					        case 'string':
 | 
				
			||||||
 | 
					          currentPrefs[key] = getStringPref(prefName, defaultValue);
 | 
				
			||||||
 | 
					          break;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return JSON.stringify(currentPrefs);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var RangedChromeActions = (function RangedChromeActionsClosure() {
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * This is for range requests
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  function RangedChromeActions(
 | 
				
			||||||
 | 
					              domWindow, contentDispositionFilename, originalRequest,
 | 
				
			||||||
 | 
					              dataListener) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ChromeActions.call(this, domWindow, contentDispositionFilename);
 | 
				
			||||||
 | 
					    this.dataListener = dataListener;
 | 
				
			||||||
 | 
					    this.originalRequest = originalRequest;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this.pdfUrl = originalRequest.URI.spec;
 | 
				
			||||||
 | 
					    this.contentLength = originalRequest.contentLength;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Pass all the headers from the original request through
 | 
				
			||||||
 | 
					    var httpHeaderVisitor = {
 | 
				
			||||||
 | 
					      headers: {},
 | 
				
			||||||
 | 
					      visitHeader: function(aHeader, aValue) {
 | 
				
			||||||
 | 
					        if (aHeader === 'Range') {
 | 
				
			||||||
 | 
					          // When loading the PDF from cache, firefox seems to set the Range
 | 
				
			||||||
 | 
					          // request header to fetch only the unfetched portions of the file
 | 
				
			||||||
 | 
					          // (e.g. 'Range: bytes=1024-'). However, we want to set this header
 | 
				
			||||||
 | 
					          // manually to fetch the PDF in chunks.
 | 
				
			||||||
 | 
					          return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        this.headers[aHeader] = aValue;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    originalRequest.visitRequestHeaders(httpHeaderVisitor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var self = this;
 | 
				
			||||||
 | 
					    var xhr_onreadystatechange = function xhr_onreadystatechange() {
 | 
				
			||||||
 | 
					      if (this.readyState === 1) { // LOADING
 | 
				
			||||||
 | 
					        var netChannel = this.channel;
 | 
				
			||||||
 | 
					        if ('nsIPrivateBrowsingChannel' in Ci &&
 | 
				
			||||||
 | 
					            netChannel instanceof Ci.nsIPrivateBrowsingChannel) {
 | 
				
			||||||
 | 
					          var docIsPrivate = self.isInPrivateBrowsing();
 | 
				
			||||||
 | 
					          netChannel.setPrivate(docIsPrivate);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    var getXhr = function getXhr() {
 | 
				
			||||||
 | 
					      const XMLHttpRequest = Components.Constructor(
 | 
				
			||||||
 | 
					          '@mozilla.org/xmlextras/xmlhttprequest;1');
 | 
				
			||||||
 | 
					      var xhr = new XMLHttpRequest();
 | 
				
			||||||
 | 
					      xhr.addEventListener('readystatechange', xhr_onreadystatechange);
 | 
				
			||||||
 | 
					      return xhr;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this.networkManager = new NetworkManager(this.pdfUrl, {
 | 
				
			||||||
 | 
					      httpHeaders: httpHeaderVisitor.headers,
 | 
				
			||||||
 | 
					      getXhr: getXhr
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // If we are in range request mode, this means we manually issued xhr
 | 
				
			||||||
 | 
					    // requests, which we need to abort when we leave the page
 | 
				
			||||||
 | 
					    domWindow.addEventListener('unload', function unload(e) {
 | 
				
			||||||
 | 
					      self.networkManager.abortAllRequests();
 | 
				
			||||||
 | 
					      domWindow.removeEventListener(e.type, unload);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  RangedChromeActions.prototype = Object.create(ChromeActions.prototype);
 | 
				
			||||||
 | 
					  var proto = RangedChromeActions.prototype;
 | 
				
			||||||
 | 
					  proto.constructor = RangedChromeActions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  proto.initPassiveLoading = function RangedChromeActions_initPassiveLoading() {
 | 
				
			||||||
 | 
					    this.originalRequest.cancel(Cr.NS_BINDING_ABORTED);
 | 
				
			||||||
 | 
					    this.originalRequest = null;
 | 
				
			||||||
 | 
					    this.domWindow.postMessage({
 | 
				
			||||||
 | 
					      pdfjsLoadAction: 'supportsRangedLoading',
 | 
				
			||||||
 | 
					      pdfUrl: this.pdfUrl,
 | 
				
			||||||
 | 
					      length: this.contentLength,
 | 
				
			||||||
 | 
					      data: this.dataListener.getData()
 | 
				
			||||||
 | 
					    }, '*');
 | 
				
			||||||
 | 
					    this.dataListener = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  proto.requestDataRange = function RangedChromeActions_requestDataRange(args) {
 | 
				
			||||||
 | 
					    var begin = args.begin;
 | 
				
			||||||
 | 
					    var end = args.end;
 | 
				
			||||||
 | 
					    var domWindow = this.domWindow;
 | 
				
			||||||
 | 
					    // TODO(mack): Support error handler. We're not currently not handling
 | 
				
			||||||
 | 
					    // errors from chrome code for non-range requests, so this doesn't
 | 
				
			||||||
 | 
					    // seem high-pri
 | 
				
			||||||
 | 
					    this.networkManager.requestRange(begin, end, {
 | 
				
			||||||
 | 
					      onDone: function RangedChromeActions_onDone(args) {
 | 
				
			||||||
 | 
					        domWindow.postMessage({
 | 
				
			||||||
 | 
					          pdfjsLoadAction: 'range',
 | 
				
			||||||
 | 
					          begin: args.begin,
 | 
				
			||||||
 | 
					          chunk: args.chunk
 | 
				
			||||||
 | 
					        }, '*');
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      onProgress: function RangedChromeActions_onProgress(evt) {
 | 
				
			||||||
 | 
					        domWindow.postMessage({
 | 
				
			||||||
 | 
					          pdfjsLoadAction: 'rangeProgress',
 | 
				
			||||||
 | 
					          loaded: evt.loaded,
 | 
				
			||||||
 | 
					        }, '*');
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return RangedChromeActions;
 | 
				
			||||||
 | 
					})();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var StandardChromeActions = (function StandardChromeActionsClosure() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * This is for a single network stream
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  function StandardChromeActions(domWindow, contentDispositionFilename,
 | 
				
			||||||
 | 
					                                 dataListener) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ChromeActions.call(this, domWindow, contentDispositionFilename);
 | 
				
			||||||
 | 
					    this.dataListener = dataListener;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  StandardChromeActions.prototype = Object.create(ChromeActions.prototype);
 | 
				
			||||||
 | 
					  var proto = StandardChromeActions.prototype;
 | 
				
			||||||
 | 
					  proto.constructor = StandardChromeActions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  proto.initPassiveLoading =
 | 
				
			||||||
 | 
					      function StandardChromeActions_initPassiveLoading() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!this.dataListener) {
 | 
				
			||||||
 | 
					      return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var self = this;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this.dataListener.onprogress = function ChromeActions_dataListenerProgress(
 | 
				
			||||||
 | 
					                                      loaded, total) {
 | 
				
			||||||
 | 
					      self.domWindow.postMessage({
 | 
				
			||||||
 | 
					        pdfjsLoadAction: 'progress',
 | 
				
			||||||
 | 
					        loaded: loaded,
 | 
				
			||||||
 | 
					        total: total
 | 
				
			||||||
 | 
					      }, '*');
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this.dataListener.oncomplete = function ChromeActions_dataListenerComplete(
 | 
				
			||||||
 | 
					                                      data, errorCode) {
 | 
				
			||||||
 | 
					      self.domWindow.postMessage({
 | 
				
			||||||
 | 
					        pdfjsLoadAction: 'complete',
 | 
				
			||||||
 | 
					        data: data,
 | 
				
			||||||
 | 
					        errorCode: errorCode
 | 
				
			||||||
 | 
					      }, '*');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      delete self.dataListener;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return StandardChromeActions;
 | 
				
			||||||
 | 
					})();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Event listener to trigger chrome privedged code.
 | 
				
			||||||
 | 
					function RequestListener(actions) {
 | 
				
			||||||
 | 
					  this.actions = actions;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					// Receive an event and synchronously or asynchronously responds.
 | 
				
			||||||
 | 
					RequestListener.prototype.receive = function(event) {
 | 
				
			||||||
 | 
					  var message = event.target;
 | 
				
			||||||
 | 
					  var doc = message.ownerDocument;
 | 
				
			||||||
 | 
					  var action = event.detail.action;
 | 
				
			||||||
 | 
					  var data = event.detail.data;
 | 
				
			||||||
 | 
					  var sync = event.detail.sync;
 | 
				
			||||||
 | 
					  var actions = this.actions;
 | 
				
			||||||
 | 
					  if (!(action in actions)) {
 | 
				
			||||||
 | 
					    log('Unknown action: ' + action);
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (sync) {
 | 
				
			||||||
 | 
					    var response = actions[action].call(this.actions, data);
 | 
				
			||||||
 | 
					    var detail = event.detail;
 | 
				
			||||||
 | 
					    detail.__exposedProps__ = {response: 'r'};
 | 
				
			||||||
 | 
					    detail.response = response;
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    var response;
 | 
				
			||||||
 | 
					    if (!event.detail.callback) {
 | 
				
			||||||
 | 
					      doc.documentElement.removeChild(message);
 | 
				
			||||||
 | 
					      response = null;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      response = function sendResponse(response) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					          var listener = doc.createEvent('CustomEvent');
 | 
				
			||||||
 | 
					          listener.initCustomEvent('pdf.js.response', true, false,
 | 
				
			||||||
 | 
					                                   {response: response,
 | 
				
			||||||
 | 
					                                    __exposedProps__: {response: 'r'}});
 | 
				
			||||||
 | 
					          return message.dispatchEvent(listener);
 | 
				
			||||||
 | 
					        } catch (e) {
 | 
				
			||||||
 | 
					          // doc is no longer accessible because the requestor is already
 | 
				
			||||||
 | 
					          // gone. unloaded content cannot receive the response anyway.
 | 
				
			||||||
 | 
					          return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    actions[action].call(this.actions, data, response);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Forwards events from the eventElement to the contentWindow only if the
 | 
				
			||||||
 | 
					// content window matches the currently selected browser window.
 | 
				
			||||||
 | 
					function FindEventManager(eventElement, contentWindow, chromeWindow) {
 | 
				
			||||||
 | 
					  this.types = ['find',
 | 
				
			||||||
 | 
					                'findagain',
 | 
				
			||||||
 | 
					                'findhighlightallchange',
 | 
				
			||||||
 | 
					                'findcasesensitivitychange'];
 | 
				
			||||||
 | 
					  this.chromeWindow = chromeWindow;
 | 
				
			||||||
 | 
					  this.contentWindow = contentWindow;
 | 
				
			||||||
 | 
					  this.eventElement = eventElement;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FindEventManager.prototype.bind = function() {
 | 
				
			||||||
 | 
					  var unload = function(e) {
 | 
				
			||||||
 | 
					    this.unbind();
 | 
				
			||||||
 | 
					    this.contentWindow.removeEventListener(e.type, unload);
 | 
				
			||||||
 | 
					  }.bind(this);
 | 
				
			||||||
 | 
					  this.contentWindow.addEventListener('unload', unload);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (var i = 0; i < this.types.length; i++) {
 | 
				
			||||||
 | 
					    var type = this.types[i];
 | 
				
			||||||
 | 
					    this.eventElement.addEventListener(type, this, true);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FindEventManager.prototype.handleEvent = function(e) {
 | 
				
			||||||
 | 
					  var chromeWindow = this.chromeWindow;
 | 
				
			||||||
 | 
					  var contentWindow = this.contentWindow;
 | 
				
			||||||
 | 
					  // Only forward the events if they are for our dom window.
 | 
				
			||||||
 | 
					  if (chromeWindow.gBrowser.selectedBrowser.contentWindow === contentWindow) {
 | 
				
			||||||
 | 
					    var detail = e.detail;
 | 
				
			||||||
 | 
					    detail.__exposedProps__ = {
 | 
				
			||||||
 | 
					      query: 'r',
 | 
				
			||||||
 | 
					      caseSensitive: 'r',
 | 
				
			||||||
 | 
					      highlightAll: 'r',
 | 
				
			||||||
 | 
					      findPrevious: 'r'
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    var forward = contentWindow.document.createEvent('CustomEvent');
 | 
				
			||||||
 | 
					    forward.initCustomEvent(e.type, true, true, detail);
 | 
				
			||||||
 | 
					    contentWindow.dispatchEvent(forward);
 | 
				
			||||||
 | 
					    e.preventDefault();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FindEventManager.prototype.unbind = function() {
 | 
				
			||||||
 | 
					  for (var i = 0; i < this.types.length; i++) {
 | 
				
			||||||
 | 
					    var type = this.types[i];
 | 
				
			||||||
 | 
					    this.eventElement.removeEventListener(type, this, true);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function PdfStreamConverter() {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PdfStreamConverter.prototype = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // properties required for XPCOM registration:
 | 
				
			||||||
 | 
					  classID: Components.ID('{PDFJSSCRIPT_STREAM_CONVERTER_ID}'),
 | 
				
			||||||
 | 
					  classDescription: 'pdf.js Component',
 | 
				
			||||||
 | 
					  contractID: '@mozilla.org/streamconv;1?from=application/pdf&to=*/*',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  QueryInterface: XPCOMUtils.generateQI([
 | 
				
			||||||
 | 
					      Ci.nsISupports,
 | 
				
			||||||
 | 
					      Ci.nsIStreamConverter,
 | 
				
			||||||
 | 
					      Ci.nsIStreamListener,
 | 
				
			||||||
 | 
					      Ci.nsIRequestObserver
 | 
				
			||||||
 | 
					  ]),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /*
 | 
				
			||||||
 | 
					   * This component works as such:
 | 
				
			||||||
 | 
					   * 1. asyncConvertData stores the listener
 | 
				
			||||||
 | 
					   * 2. onStartRequest creates a new channel, streams the viewer
 | 
				
			||||||
 | 
					   * 3. If range requests are supported:
 | 
				
			||||||
 | 
					   *      3.1. Leave the request open until the viewer is ready to switch to
 | 
				
			||||||
 | 
					   *           range requests.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   *    If range rquests are not supported:
 | 
				
			||||||
 | 
					   *      3.1. Read the stream as it's loaded in onDataAvailable to send
 | 
				
			||||||
 | 
					   *           to the viewer
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * The convert function just returns the stream, it's just the synchronous
 | 
				
			||||||
 | 
					   * version of asyncConvertData.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // nsIStreamConverter::convert
 | 
				
			||||||
 | 
					  convert: function(aFromStream, aFromType, aToType, aCtxt) {
 | 
				
			||||||
 | 
					    throw Cr.NS_ERROR_NOT_IMPLEMENTED;
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // nsIStreamConverter::asyncConvertData
 | 
				
			||||||
 | 
					  asyncConvertData: function(aFromType, aToType, aListener, aCtxt) {
 | 
				
			||||||
 | 
					    // Store the listener passed to us
 | 
				
			||||||
 | 
					    this.listener = aListener;
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // nsIStreamListener::onDataAvailable
 | 
				
			||||||
 | 
					  onDataAvailable: function(aRequest, aContext, aInputStream, aOffset, aCount) {
 | 
				
			||||||
 | 
					    if (!this.dataListener) {
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var binaryStream = this.binaryStream;
 | 
				
			||||||
 | 
					    binaryStream.setInputStream(aInputStream);
 | 
				
			||||||
 | 
					    var chunk = binaryStream.readByteArray(aCount);
 | 
				
			||||||
 | 
					    this.dataListener.append(chunk);
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // nsIRequestObserver::onStartRequest
 | 
				
			||||||
 | 
					  onStartRequest: function(aRequest, aContext) {
 | 
				
			||||||
 | 
					    // Setup the request so we can use it below.
 | 
				
			||||||
 | 
					    var isHttpRequest = false;
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      aRequest.QueryInterface(Ci.nsIHttpChannel);
 | 
				
			||||||
 | 
					      isHttpRequest = true;
 | 
				
			||||||
 | 
					    } catch (e) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var rangeRequest = false;
 | 
				
			||||||
 | 
					    if (isHttpRequest) {
 | 
				
			||||||
 | 
					      var contentEncoding = 'identity';
 | 
				
			||||||
 | 
					      try {
 | 
				
			||||||
 | 
					        contentEncoding = aRequest.getResponseHeader('Content-Encoding');
 | 
				
			||||||
 | 
					      } catch (e) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      var acceptRanges;
 | 
				
			||||||
 | 
					      try {
 | 
				
			||||||
 | 
					        acceptRanges = aRequest.getResponseHeader('Accept-Ranges');
 | 
				
			||||||
 | 
					      } catch (e) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      var hash = aRequest.URI.ref;
 | 
				
			||||||
 | 
					      rangeRequest = contentEncoding === 'identity' &&
 | 
				
			||||||
 | 
					                     acceptRanges === 'bytes' &&
 | 
				
			||||||
 | 
					                     aRequest.contentLength >= 0 &&
 | 
				
			||||||
 | 
					                     hash.indexOf('disableRange=true') < 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    aRequest.QueryInterface(Ci.nsIChannel);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    aRequest.QueryInterface(Ci.nsIWritablePropertyBag);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var contentDispositionFilename;
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      contentDispositionFilename = aRequest.contentDispositionFilename;
 | 
				
			||||||
 | 
					    } catch (e) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Change the content type so we don't get stuck in a loop.
 | 
				
			||||||
 | 
					    aRequest.setProperty('contentType', aRequest.contentType);
 | 
				
			||||||
 | 
					    aRequest.contentType = 'text/html';
 | 
				
			||||||
 | 
					    if (isHttpRequest) {
 | 
				
			||||||
 | 
					      // We trust PDF viewer, using no CSP
 | 
				
			||||||
 | 
					      aRequest.setResponseHeader('Content-Security-Policy', '', false);
 | 
				
			||||||
 | 
					      aRequest.setResponseHeader('Content-Security-Policy-Report-Only', '',
 | 
				
			||||||
 | 
					                                 false);
 | 
				
			||||||
 | 
					      aRequest.setResponseHeader('X-Content-Security-Policy', '', false);
 | 
				
			||||||
 | 
					      aRequest.setResponseHeader('X-Content-Security-Policy-Report-Only', '',
 | 
				
			||||||
 | 
					                                 false);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    PdfJsTelemetry.onViewerIsUsed();
 | 
				
			||||||
 | 
					    PdfJsTelemetry.onDocumentSize(aRequest.contentLength);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Creating storage for PDF data
 | 
				
			||||||
 | 
					    var contentLength = aRequest.contentLength;
 | 
				
			||||||
 | 
					    this.dataListener = new PdfDataListener(contentLength);
 | 
				
			||||||
 | 
					    this.binaryStream = Cc['@mozilla.org/binaryinputstream;1']
 | 
				
			||||||
 | 
					                        .createInstance(Ci.nsIBinaryInputStream);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Create a new channel that is viewer loaded as a resource.
 | 
				
			||||||
 | 
					    var ioService = Services.io;
 | 
				
			||||||
 | 
					    var channel = ioService.newChannel(
 | 
				
			||||||
 | 
					                    PDF_VIEWER_WEB_PAGE, null, null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var listener = this.listener;
 | 
				
			||||||
 | 
					    var dataListener = this.dataListener;
 | 
				
			||||||
 | 
					    // Proxy all the request observer calls, when it gets to onStopRequest
 | 
				
			||||||
 | 
					    // we can get the dom window.  We also intentionally pass on the original
 | 
				
			||||||
 | 
					    // request(aRequest) below so we don't overwrite the original channel and
 | 
				
			||||||
 | 
					    // trigger an assertion.
 | 
				
			||||||
 | 
					    var proxy = {
 | 
				
			||||||
 | 
					      onStartRequest: function(request, context) {
 | 
				
			||||||
 | 
					        listener.onStartRequest(aRequest, context);
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      onDataAvailable: function(request, context, inputStream, offset, count) {
 | 
				
			||||||
 | 
					        listener.onDataAvailable(aRequest, context, inputStream, offset, count);
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      onStopRequest: function(request, context, statusCode) {
 | 
				
			||||||
 | 
					        // We get the DOM window here instead of before the request since it
 | 
				
			||||||
 | 
					        // may have changed during a redirect.
 | 
				
			||||||
 | 
					        var domWindow = getDOMWindow(channel);
 | 
				
			||||||
 | 
					        var actions;
 | 
				
			||||||
 | 
					        if (rangeRequest) {
 | 
				
			||||||
 | 
					          actions = new RangedChromeActions(
 | 
				
			||||||
 | 
					              domWindow, contentDispositionFilename, aRequest, dataListener);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					          actions = new StandardChromeActions(
 | 
				
			||||||
 | 
					              domWindow, contentDispositionFilename, dataListener);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        var requestListener = new RequestListener(actions);
 | 
				
			||||||
 | 
					        domWindow.addEventListener(PDFJS_EVENT_ID, function(event) {
 | 
				
			||||||
 | 
					          requestListener.receive(event);
 | 
				
			||||||
 | 
					        }, false, true);
 | 
				
			||||||
 | 
					        if (actions.supportsIntegratedFind()) {
 | 
				
			||||||
 | 
					          var chromeWindow = getChromeWindow(domWindow);
 | 
				
			||||||
 | 
					          var findEventManager = new FindEventManager(chromeWindow.gFindBar,
 | 
				
			||||||
 | 
					                                                      domWindow,
 | 
				
			||||||
 | 
					                                                      chromeWindow);
 | 
				
			||||||
 | 
					          findEventManager.bind();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        listener.onStopRequest(aRequest, context, statusCode);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Keep the URL the same so the browser sees it as the same.
 | 
				
			||||||
 | 
					    channel.originalURI = aRequest.URI;
 | 
				
			||||||
 | 
					    channel.loadGroup = aRequest.loadGroup;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // We can use resource principal when data is fetched by the chrome
 | 
				
			||||||
 | 
					    // e.g. useful for NoScript
 | 
				
			||||||
 | 
					    var securityManager = Cc['@mozilla.org/scriptsecuritymanager;1']
 | 
				
			||||||
 | 
					                          .getService(Ci.nsIScriptSecurityManager);
 | 
				
			||||||
 | 
					    var uri = ioService.newURI(PDF_VIEWER_WEB_PAGE, null, null);
 | 
				
			||||||
 | 
					    // FF16 and below had getCodebasePrincipal, it was replaced by
 | 
				
			||||||
 | 
					    // getNoAppCodebasePrincipal (bug 758258).
 | 
				
			||||||
 | 
					    var resourcePrincipal = 'getNoAppCodebasePrincipal' in securityManager ?
 | 
				
			||||||
 | 
					                            securityManager.getNoAppCodebasePrincipal(uri) :
 | 
				
			||||||
 | 
					                            securityManager.getCodebasePrincipal(uri);
 | 
				
			||||||
 | 
					    aRequest.owner = resourcePrincipal;
 | 
				
			||||||
 | 
					    channel.asyncOpen(proxy, aContext);
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // nsIRequestObserver::onStopRequest
 | 
				
			||||||
 | 
					  onStopRequest: function(aRequest, aContext, aStatusCode) {
 | 
				
			||||||
 | 
					    if (!this.dataListener) {
 | 
				
			||||||
 | 
					      // Do nothing
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (Components.isSuccessCode(aStatusCode))
 | 
				
			||||||
 | 
					      this.dataListener.finish();
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					      this.dataListener.error(aStatusCode);
 | 
				
			||||||
 | 
					    delete this.dataListener;
 | 
				
			||||||
 | 
					    delete this.binaryStream;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var NSGetFactory = XPCOMUtils.generateNSGetFactory([PdfStreamConverter]);
 | 
				
			||||||
							
								
								
									
										18
									
								
								public/vendor/pdfjs/l10n/es/chrome.properties
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								public/vendor/pdfjs/l10n/es/chrome.properties
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					# Copyright 2012 Mozilla Foundation
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					# you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					# You may obtain a copy of the License at
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					# distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					# See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					# limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Chrome notification bar messages and buttons
 | 
				
			||||||
 | 
					unsupported_feature=Es posible que este documento PDF no se muestre correctamente.
 | 
				
			||||||
 | 
					open_with_different_viewer=Abrir con un visor diferente
 | 
				
			||||||
 | 
					open_with_different_viewer.accessKey=a
 | 
				
			||||||
							
								
								
									
										8
									
								
								public/vendor/pdfjs/l10n/es/metadata.inc
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								public/vendor/pdfjs/l10n/es/metadata.inc
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					    <em:localized>
 | 
				
			||||||
 | 
					      <Description>
 | 
				
			||||||
 | 
					        <em:locale>es</em:locale>
 | 
				
			||||||
 | 
					        <em:name>Visor de PDF</em:name>
 | 
				
			||||||
 | 
					        <em:description>Usa HTML5 para mostrar archivos PDF directamente en Firefox.</em:description>
 | 
				
			||||||
 | 
					      </Description>
 | 
				
			||||||
 | 
					    </em:localized>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										141
									
								
								public/vendor/pdfjs/l10n/es/viewer.properties
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								public/vendor/pdfjs/l10n/es/viewer.properties
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,141 @@
 | 
				
			|||||||
 | 
					# Copyright 2012 Mozilla Foundation
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					# you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					# You may obtain a copy of the License at
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					# distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					# See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					# limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Main toolbar buttons (tooltips and alt text for images)
 | 
				
			||||||
 | 
					previous.title=Página anterior
 | 
				
			||||||
 | 
					previous_label=Anterior
 | 
				
			||||||
 | 
					next.title=Página siguiente
 | 
				
			||||||
 | 
					next_label=Siguiente
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# LOCALIZATION NOTE (page_label, page_of):
 | 
				
			||||||
 | 
					# These strings are concatenated to form the "Page: X of Y" string.
 | 
				
			||||||
 | 
					# Do not translate "{{pageCount}}", it will be substituted with a number
 | 
				
			||||||
 | 
					# representing the total number of pages.
 | 
				
			||||||
 | 
					page_label=Página:
 | 
				
			||||||
 | 
					page_of=de {{pageCount}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					zoom_out.title=Reducir
 | 
				
			||||||
 | 
					zoom_out_label=Reducir
 | 
				
			||||||
 | 
					zoom_in.title=Aumentar
 | 
				
			||||||
 | 
					zoom_in_label=Aumentar
 | 
				
			||||||
 | 
					zoom.title=Ampliación
 | 
				
			||||||
 | 
					presentation_mode.title=Cambiar al modo de presentación
 | 
				
			||||||
 | 
					presentation_mode_label=Modo de presentación
 | 
				
			||||||
 | 
					open_file.title=Abrir un archivo
 | 
				
			||||||
 | 
					open_file_label=Abrir
 | 
				
			||||||
 | 
					print.title=Imprimir
 | 
				
			||||||
 | 
					print_label=Imprimir
 | 
				
			||||||
 | 
					download.title=Descargar
 | 
				
			||||||
 | 
					download_label=Descargar
 | 
				
			||||||
 | 
					bookmark.title=Vista actual (para copiar o abrir en otra ventana)
 | 
				
			||||||
 | 
					bookmark_label=Vista actual
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Secondary toolbar and context menu
 | 
				
			||||||
 | 
					tools.title=Herramientas
 | 
				
			||||||
 | 
					tools_label=Herramientas
 | 
				
			||||||
 | 
					first_page.title=Ir a la primera página
 | 
				
			||||||
 | 
					first_page.label=Ir a la primera página
 | 
				
			||||||
 | 
					first_page_label=Ir a la primera página
 | 
				
			||||||
 | 
					last_page.title=Ir a la última página
 | 
				
			||||||
 | 
					last_page.label=Ir a la última página
 | 
				
			||||||
 | 
					last_page_label=Ir a la última página
 | 
				
			||||||
 | 
					page_rotate_cw.title=Girar a la derecha
 | 
				
			||||||
 | 
					page_rotate_cw.label=Girar a la derecha
 | 
				
			||||||
 | 
					page_rotate_cw_label=Girar a la derecha
 | 
				
			||||||
 | 
					page_rotate_ccw.title=Girar a la izquierda
 | 
				
			||||||
 | 
					page_rotate_ccw.label=Girar a la izquierda
 | 
				
			||||||
 | 
					page_rotate_ccw_label=Girar a la izquierda
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					hand_tool_enable.title=Activar la herramienta Mano
 | 
				
			||||||
 | 
					hand_tool_enable_label=Activar la herramienta Mano
 | 
				
			||||||
 | 
					hand_tool_disable.title=Desactivar la herramienta Mano
 | 
				
			||||||
 | 
					hand_tool_disable_label=Desactivar la herramienta Mano
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Tooltips and alt text for side panel toolbar buttons
 | 
				
			||||||
 | 
					# (the _label strings are alt text for the buttons, the .title strings are
 | 
				
			||||||
 | 
					# tooltips)
 | 
				
			||||||
 | 
					toggle_sidebar.title=Mostrar u ocultar la barra lateral
 | 
				
			||||||
 | 
					toggle_sidebar_label=Conmutar la barra lateral
 | 
				
			||||||
 | 
					outline.title=Mostrar el esquema del documento
 | 
				
			||||||
 | 
					outline_label=Esquema del documento
 | 
				
			||||||
 | 
					thumbs.title=Mostrar las miniaturas
 | 
				
			||||||
 | 
					thumbs_label=Miniaturas
 | 
				
			||||||
 | 
					findbar.title=Buscar en el documento
 | 
				
			||||||
 | 
					findbar_label=Buscar
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Thumbnails panel item (tooltip and alt text for images)
 | 
				
			||||||
 | 
					# LOCALIZATION NOTE (thumb_page_title): "{{page}}" will be replaced by the page
 | 
				
			||||||
 | 
					# number.
 | 
				
			||||||
 | 
					thumb_page_title=Página {{page}}
 | 
				
			||||||
 | 
					# LOCALIZATION NOTE (thumb_page_canvas): "{{page}}" will be replaced by the page
 | 
				
			||||||
 | 
					# number.
 | 
				
			||||||
 | 
					thumb_page_canvas=Miniatura de la página {{page}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Find panel button title and messages
 | 
				
			||||||
 | 
					find_label=Buscar:
 | 
				
			||||||
 | 
					find_previous.title=Ir a la frase encontrada anterior
 | 
				
			||||||
 | 
					find_previous_label=Anterior
 | 
				
			||||||
 | 
					find_next.title=Ir a la frase encontrada siguiente
 | 
				
			||||||
 | 
					find_next_label=Siguiente
 | 
				
			||||||
 | 
					find_highlight=Resaltar todo
 | 
				
			||||||
 | 
					find_match_case_label=Coincidir mayúsculas y minúsculas
 | 
				
			||||||
 | 
					find_reached_top=Se alcanzó el inicio del documento, se continúa desde el final
 | 
				
			||||||
 | 
					find_reached_bottom=Se alcanzó el final del documento, se continúa desde el inicio
 | 
				
			||||||
 | 
					find_not_found=No se encontró la frase
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Error panel labels
 | 
				
			||||||
 | 
					error_more_info=Más información
 | 
				
			||||||
 | 
					error_less_info=Menos información
 | 
				
			||||||
 | 
					error_close=Cerrar
 | 
				
			||||||
 | 
					# LOCALIZATION NOTE (error_version_info): "{{version}}" and "{{build}}" will be
 | 
				
			||||||
 | 
					# replaced by the PDF.JS version and build ID.
 | 
				
			||||||
 | 
					error_version_info=PDF.js v{{version}} (compilación: {{build}})
 | 
				
			||||||
 | 
					# LOCALIZATION NOTE (error_message): "{{message}}" will be replaced by an
 | 
				
			||||||
 | 
					# english string describing the error.
 | 
				
			||||||
 | 
					error_message=Mensaje: {{message}}
 | 
				
			||||||
 | 
					# LOCALIZATION NOTE (error_stack): "{{stack}}" will be replaced with a stack
 | 
				
			||||||
 | 
					# trace.
 | 
				
			||||||
 | 
					error_stack=Pila: {{stack}}
 | 
				
			||||||
 | 
					# LOCALIZATION NOTE (error_file): "{{file}}" will be replaced with a filename
 | 
				
			||||||
 | 
					error_file=Archivo: {{file}}
 | 
				
			||||||
 | 
					# LOCALIZATION NOTE (error_line): "{{line}}" will be replaced with a line number
 | 
				
			||||||
 | 
					error_line=Línea: {{line}}
 | 
				
			||||||
 | 
					rendering_error=Ocurrió un error al renderizar la página.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Predefined zoom values
 | 
				
			||||||
 | 
					page_scale_width=Anchura de la página
 | 
				
			||||||
 | 
					page_scale_fit=Ajustar a la página
 | 
				
			||||||
 | 
					page_scale_auto=Ampliación automática
 | 
				
			||||||
 | 
					page_scale_actual=Tamaño real
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Loading indicator messages
 | 
				
			||||||
 | 
					loading_error_indicator=Error
 | 
				
			||||||
 | 
					loading_error=Ocurrió un error al cargar el PDF.
 | 
				
			||||||
 | 
					invalid_file_error=El archivo PDF no es válido o está dañado.
 | 
				
			||||||
 | 
					missing_file_error=Falta el archivo PDF.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# LOCALIZATION NOTE (text_annotation_type.alt): This is used as a tooltip.
 | 
				
			||||||
 | 
					# "{{type}}" will be replaced with an annotation type from a list defined in
 | 
				
			||||||
 | 
					# the PDF spec (32000-1:2008 Table 169 – Annotation types).
 | 
				
			||||||
 | 
					# Some common types are e.g.: "Check", "Text", "Comment", "Note"
 | 
				
			||||||
 | 
					text_annotation_type.alt=[Anotación {{type}}]
 | 
				
			||||||
 | 
					password_label=Escriba la contraseña para abrir este archivo PDF.
 | 
				
			||||||
 | 
					password_invalid=La contraseña no es válida. Inténtelo de nuevo.
 | 
				
			||||||
 | 
					password_ok=Aceptar
 | 
				
			||||||
 | 
					password_cancel=Cancelar
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					printing_not_supported=Aviso: Este navegador no es compatible completamente con la impresión.
 | 
				
			||||||
 | 
					printing_not_ready=Aviso: El PDF no se ha cargado completamente para su impresión.
 | 
				
			||||||
 | 
					web_fonts_disabled=Se han desactivado los tipos de letra web: no se pueden usar los tipos de letra incrustados en el PDF.
 | 
				
			||||||
 | 
					document_colors_disabled=No se permite que los documentos PDF usen sus propios colores: la opción «Permitir que las páginas elijan sus propios colores» está desactivada en el navegador.
 | 
				
			||||||
							
								
								
									
										19
									
								
								public/vendor/pdfjs/l10n/no/chrome.properties
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								public/vendor/pdfjs/l10n/no/chrome.properties
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					# Copyright 2012 Mozilla Foundation
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					# you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					# You may obtain a copy of the License at
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					# distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					# See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					# limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Chrome notification bar messages and buttons
 | 
				
			||||||
 | 
					unsupported_feature=Dette PDF-dokumentet vert kanskje ikkje vist rett.
 | 
				
			||||||
 | 
					open_with_different_viewer=Opne med eit anna visingsprogram
 | 
				
			||||||
 | 
					open_with_different_viewer.accessKey=o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										8
									
								
								public/vendor/pdfjs/l10n/no/metadata.inc
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								public/vendor/pdfjs/l10n/no/metadata.inc
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					    <em:localized>
 | 
				
			||||||
 | 
					      <Description>
 | 
				
			||||||
 | 
					        <em:locale>no</em:locale>
 | 
				
			||||||
 | 
					        <em:name>PDF Viewer</em:name>
 | 
				
			||||||
 | 
					        <em:description>Bruker HTML5 for å vise PDF-filer direkte i Firefox.</em:description>
 | 
				
			||||||
 | 
					      </Description>
 | 
				
			||||||
 | 
					    </em:localized>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										134
									
								
								public/vendor/pdfjs/l10n/no/viewer.properties
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								public/vendor/pdfjs/l10n/no/viewer.properties
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,134 @@
 | 
				
			|||||||
 | 
					# Copyright 2012 Mozilla Foundation
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					# you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					# You may obtain a copy of the License at
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					# distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					# See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					# limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Main toolbar buttons (tooltips and alt text for images)
 | 
				
			||||||
 | 
					previous.title=Førre Side
 | 
				
			||||||
 | 
					previous_label=Førre
 | 
				
			||||||
 | 
					next.title=Neste side
 | 
				
			||||||
 | 
					next_label=Neste
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# LOCALIZATION NOTE (page_label, page_of):
 | 
				
			||||||
 | 
					# These strings are concatenated to form the "Page: X of Y" string.
 | 
				
			||||||
 | 
					# Do not translate "{{pageCount}}", it will be substituted with a number
 | 
				
			||||||
 | 
					# representing the total number of pages.
 | 
				
			||||||
 | 
					page_label=Side:
 | 
				
			||||||
 | 
					page_of=av {{pageCount}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					zoom_out.title=Zoom ut
 | 
				
			||||||
 | 
					zoom_out_label=Zoom ut
 | 
				
			||||||
 | 
					zoom_in.title=Zoom inn
 | 
				
			||||||
 | 
					zoom_in_label=Zoom inn
 | 
				
			||||||
 | 
					zoom.title=Zoom
 | 
				
			||||||
 | 
					presentation_mode.title=Bytt til presentasjonsmodus
 | 
				
			||||||
 | 
					presentation_mode_label=Presentasjonsmodus
 | 
				
			||||||
 | 
					open_file.title=Opne fil
 | 
				
			||||||
 | 
					open_file_label=Opne
 | 
				
			||||||
 | 
					print.title=Skriv ut
 | 
				
			||||||
 | 
					print_label=Skriv ut
 | 
				
			||||||
 | 
					download.title=Last ned
 | 
				
			||||||
 | 
					download_label=Last ned
 | 
				
			||||||
 | 
					bookmark.title=Gjeldande visning (kopier eller opne i nytt vindauge)
 | 
				
			||||||
 | 
					bookmark_label=Gjeldende visning
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Secondary toolbar and context menu
 | 
				
			||||||
 | 
					tools.title=Verktøy
 | 
				
			||||||
 | 
					tools_label=Verktøy
 | 
				
			||||||
 | 
					first_page.title=Gå til første side
 | 
				
			||||||
 | 
					first_page.label=Gå til første side
 | 
				
			||||||
 | 
					first_page_label=Gå til første side
 | 
				
			||||||
 | 
					last_page.title=Gå til siste side
 | 
				
			||||||
 | 
					last_page.label=Gå til siste side
 | 
				
			||||||
 | 
					last_page_label=Gå til siste side
 | 
				
			||||||
 | 
					page_rotate_cw.title=Roter med klokka
 | 
				
			||||||
 | 
					page_rotate_cw.label=Roter med klokka
 | 
				
			||||||
 | 
					page_rotate_cw_label=Roter med klokka
 | 
				
			||||||
 | 
					page_rotate_ccw.title=Roter mot klokka
 | 
				
			||||||
 | 
					page_rotate_ccw.label=Roter mot klokka
 | 
				
			||||||
 | 
					page_rotate_ccw_label=Roter mot klokka
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Tooltips and alt text for side panel toolbar buttons
 | 
				
			||||||
 | 
					# (the _label strings are alt text for the buttons, the .title strings are
 | 
				
			||||||
 | 
					# tooltips)
 | 
				
			||||||
 | 
					toggle_sidebar.title=Veksle Sidebar
 | 
				
			||||||
 | 
					toggle_sidebar_label=Veksle Sidebar
 | 
				
			||||||
 | 
					outline.title=Vis Document Outline
 | 
				
			||||||
 | 
					outline_label=Document Outline
 | 
				
			||||||
 | 
					thumbs.title=Vis miniatyrbilder
 | 
				
			||||||
 | 
					thumbs_label=Miniatyrbilder
 | 
				
			||||||
 | 
					findbar.title=Finne i Dokument
 | 
				
			||||||
 | 
					findbar_label=Finn
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Thumbnails panel item (tooltip and alt text for images)
 | 
				
			||||||
 | 
					# LOCALIZATION NOTE (thumb_page_title): "{{page}}" will be replaced by the page
 | 
				
			||||||
 | 
					# number.
 | 
				
			||||||
 | 
					thumb_page_title=Side {{page}}
 | 
				
			||||||
 | 
					# LOCALIZATION NOTE (thumb_page_canvas): "{{page}}" will be replaced by the page
 | 
				
			||||||
 | 
					# number.
 | 
				
			||||||
 | 
					thumb_page_canvas=Thumbnail av siden {{page}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Find panel button title and messages
 | 
				
			||||||
 | 
					find_label=Finn:
 | 
				
			||||||
 | 
					find_previous.title=Finn tidlegare førekomst av frasa
 | 
				
			||||||
 | 
					find_previous_label=Førre
 | 
				
			||||||
 | 
					find_next.title=Finn neste førekomst av frasa
 | 
				
			||||||
 | 
					find_next_label=Neste
 | 
				
			||||||
 | 
					find_highlight=Uthev alle
 | 
				
			||||||
 | 
					find_match_case_label=Skil store/små bokstavar
 | 
				
			||||||
 | 
					find_reached_top=Nådde toppen av dokumentet, held fram frå botnen
 | 
				
			||||||
 | 
					find_reached_bottom=Nådde botnen av dokumentet, held fram frå toppen
 | 
				
			||||||
 | 
					find_not_found=Fann ikkje teksten
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Error panel labels
 | 
				
			||||||
 | 
					error_more_info=Meir info
 | 
				
			||||||
 | 
					error_less_info=Mindre info
 | 
				
			||||||
 | 
					error_close=Lukk
 | 
				
			||||||
 | 
					# LOCALIZATION NOTE (error_version_info): "{{version}}" and "{{build}}" will be
 | 
				
			||||||
 | 
					# replaced by the PDF.JS version and build ID.
 | 
				
			||||||
 | 
					error_version_info=PDF.js v {{version}} (build: {{build}})
 | 
				
			||||||
 | 
					# LOCALIZATION NOTE (error_message): "{{message}}" will be replaced by an
 | 
				
			||||||
 | 
					# english string describing the error.
 | 
				
			||||||
 | 
					error_message=Melding: {{message}}
 | 
				
			||||||
 | 
					# LOCALIZATION NOTE (error_stack): "{{stack}}" will be replaced with a stack
 | 
				
			||||||
 | 
					# trace.
 | 
				
			||||||
 | 
					error_stack=Stakk: {{stack}}
 | 
				
			||||||
 | 
					# LOCALIZATION NOTE (error_file): "{{file}}" will be replaced with a filename
 | 
				
			||||||
 | 
					error_file=Fil: {{file}}
 | 
				
			||||||
 | 
					# LOCALIZATION NOTE (error_line): "{{line}}" will be replaced with a line number
 | 
				
			||||||
 | 
					error_line=Linje: {{line}}
 | 
				
			||||||
 | 
					rendering_error=Ein feil oppstod ved oppteikning av sida.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Predefined zoom values
 | 
				
			||||||
 | 
					page_scale_width=Sidebreidde
 | 
				
			||||||
 | 
					page_scale_fit=Tilpass til sida
 | 
				
			||||||
 | 
					page_scale_auto=Automatisk zoom
 | 
				
			||||||
 | 
					page_scale_actual=Verkeleg størrelse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Loading indicator messages
 | 
				
			||||||
 | 
					loading_error_indicator=Feil
 | 
				
			||||||
 | 
					loading_error=Ein feil oppstod ved lasting av PDF.
 | 
				
			||||||
 | 
					invalid_file_error=Ugyldig eller korrupt PDF fil.
 | 
				
			||||||
 | 
					missing_file_error=Manglande PDF-fil.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# LOCALIZATION NOTE (text_annotation_type.alt): This is used as a tooltip.
 | 
				
			||||||
 | 
					# "{{type}}" will be replaced with an annotation type from a list defined in
 | 
				
			||||||
 | 
					# the PDF spec (32000-1:2008 Table 169 – Annotation types).
 | 
				
			||||||
 | 
					# Some common types are e.g.: "Check", "Text", "Comment", "Note"
 | 
				
			||||||
 | 
					text_annotation_type.alt=[{{type}} annotasjon]
 | 
				
			||||||
 | 
					request_password=PDF er beskytta av eit passord:
 | 
				
			||||||
 | 
					invalid_password=Ugyldig passord.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					printing_not_supported=Åtvaring: Utskrift er ikkje fullstendig støtta av denne nettlesaren.
 | 
				
			||||||
 | 
					printing_not_ready=Åtvaring: PDF ikkje fullstendig innlasta for utskrift.
 | 
				
			||||||
 | 
					web_fonts_disabled=Web-fontar er avslått: Kan ikkje bruke innbundne PDF-fontar.
 | 
				
			||||||
 | 
					document_colors_disabled=PDF-dokument har ikkje løyve til å nytte eigne fargar: \'Tillat sider å velje eigne fargar\' er slått av i nettlesaren.
 | 
				
			||||||
							
								
								
									
										640
									
								
								public/vendor/pdfjs/test/resources/reftest-analyzer.xhtml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										640
									
								
								public/vendor/pdfjs/test/resources/reftest-analyzer.xhtml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,640 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<!-- vim: set shiftwidth=4 tabstop=4 autoindent noexpandtab: -->
 | 
				
			||||||
 | 
					<!-- ***** BEGIN LICENSE BLOCK *****
 | 
				
			||||||
 | 
					   - Version: MPL 1.1/GPL 2.0/LGPL 2.1
 | 
				
			||||||
 | 
					   -
 | 
				
			||||||
 | 
					   - The contents of this file are subject to the Mozilla Public License Version
 | 
				
			||||||
 | 
					   - 1.1 (the "License"); you may not use this file except in compliance with
 | 
				
			||||||
 | 
					   - the License. You may obtain a copy of the License at
 | 
				
			||||||
 | 
					   - http://www.mozilla.org/MPL/
 | 
				
			||||||
 | 
					   -
 | 
				
			||||||
 | 
					   - Software distributed under the License is distributed on an "AS IS" basis,
 | 
				
			||||||
 | 
					   - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 | 
				
			||||||
 | 
					   - for the specific language governing rights and limitations under the
 | 
				
			||||||
 | 
					   - License.
 | 
				
			||||||
 | 
					   -
 | 
				
			||||||
 | 
					   - The Original Code is reftest-analyzer.html.
 | 
				
			||||||
 | 
					   -
 | 
				
			||||||
 | 
					   - The Initial Developer of the Original Code is the Mozilla Foundation.
 | 
				
			||||||
 | 
					   - Portions created by the Initial Developer are Copyright (C) 2008
 | 
				
			||||||
 | 
					   - the Initial Developer. All Rights Reserved.
 | 
				
			||||||
 | 
					   -
 | 
				
			||||||
 | 
					   - Contributor(s):
 | 
				
			||||||
 | 
					   -   L. David Baron <dbaron@dbaron.org>, Mozilla Corporation (original author)
 | 
				
			||||||
 | 
					   -
 | 
				
			||||||
 | 
					   - Alternatively, the contents of this file may be used under the terms of
 | 
				
			||||||
 | 
					   - either the GNU General Public License Version 2 or later (the "GPL"), or
 | 
				
			||||||
 | 
					   - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 | 
				
			||||||
 | 
					   - in which case the provisions of the GPL or the LGPL are applicable instead
 | 
				
			||||||
 | 
					   - of those above. If you wish to allow use of your version of this file only
 | 
				
			||||||
 | 
					   - under the terms of either the GPL or the LGPL, and not to allow others to
 | 
				
			||||||
 | 
					   - use your version of this file under the terms of the MPL, indicate your
 | 
				
			||||||
 | 
					   - decision by deleting the provisions above and replace them with the notice
 | 
				
			||||||
 | 
					   - and other provisions required by the LGPL or the GPL. If you do not delete
 | 
				
			||||||
 | 
					   - the provisions above, a recipient may use your version of this file under
 | 
				
			||||||
 | 
					   - the terms of any one of the MPL, the GPL or the LGPL.
 | 
				
			||||||
 | 
					   -
 | 
				
			||||||
 | 
					   - ***** END LICENSE BLOCK ***** -->
 | 
				
			||||||
 | 
					<!--
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Features to add:
 | 
				
			||||||
 | 
					* make the left and right parts of the viewer independently scrollable
 | 
				
			||||||
 | 
					* make the test list filterable
 | 
				
			||||||
 | 
					** default to only showing unexpecteds
 | 
				
			||||||
 | 
					* add other ways to highlight differences other than circling?
 | 
				
			||||||
 | 
					* add zoom/pan to images
 | 
				
			||||||
 | 
					* Add ability to load log via XMLHttpRequest (also triggered via URL param)
 | 
				
			||||||
 | 
					* color the test list based on pass/fail and expected/unexpected/random/skip
 | 
				
			||||||
 | 
					* ability to load multiple logs ?
 | 
				
			||||||
 | 
					** rename them by clicking on the name and editing
 | 
				
			||||||
 | 
					** turn the test list into a collapsing tree view
 | 
				
			||||||
 | 
					** move log loading into popup from viewer UI
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					<html lang="en-US" xml:lang="en-US" xmlns="http://www.w3.org/1999/xhtml">
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
					  <title>Reftest analyzer</title>
 | 
				
			||||||
 | 
					  <style type="text/css"><![CDATA[
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  html, body { margin: 0; }
 | 
				
			||||||
 | 
					  html { padding: 0; }
 | 
				
			||||||
 | 
					  body { padding: 4px; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  #pixelarea, #itemlist, #images { position: absolute; }
 | 
				
			||||||
 | 
					  #itemlist, #images { overflow: auto; }
 | 
				
			||||||
 | 
					  #pixelarea { top: 0; left: 0; width: 320px; height: 84px; overflow: visible }
 | 
				
			||||||
 | 
					  #itemlist { top: 84px; left: 0; width: 320px; bottom: 0; }
 | 
				
			||||||
 | 
					  #images { top: 0; bottom: 0; left: 320px; right: 0; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  #leftpane { width: 320px; }
 | 
				
			||||||
 | 
					  #images { position: fixed; top: 10px; left: 340px; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  form#imgcontrols { margin: 0; display: block; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  #itemlist > table { border-collapse: collapse; }
 | 
				
			||||||
 | 
					  #itemlist > table > tbody > tr > td { border: 1px solid; padding: 1px; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  .selected { background-color: lightsteelblue; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /*
 | 
				
			||||||
 | 
					  #itemlist > table > tbody > tr.pass > td.url { background: lime; }
 | 
				
			||||||
 | 
					  #itemlist > table > tbody > tr.fail > td.url { background: red; }
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  #magnification > svg { display: block; width: 84px; height: 84px; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  #pixelinfo { font: small sans-serif; position: absolute; width: 200px; left: 84px; }
 | 
				
			||||||
 | 
					  #pixelinfo table { border-collapse: collapse; }
 | 
				
			||||||
 | 
					  #pixelinfo table th { white-space: nowrap; text-align: left; padding: 0; }
 | 
				
			||||||
 | 
					  #pixelinfo table td { font-family: monospace; padding: 0 0 0 0.25em; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  #pixelhint { display: inline; color: #88f; cursor: help; }
 | 
				
			||||||
 | 
					  #pixelhint > * { display: none; position: absolute; margin: 8px 0 0 8px; padding: 4px; width: 400px; background: #ffa; color: black; box-shadow: 3px 3px 2px #888; z-index: 1; }
 | 
				
			||||||
 | 
					  #pixelhint:hover { color: #000; }
 | 
				
			||||||
 | 
					  #pixelhint:hover > * { display: block; }
 | 
				
			||||||
 | 
					  #pixelhint p { margin: 0; }
 | 
				
			||||||
 | 
					  #pixelhint p + p { margin-top: 1em; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ]]></style>
 | 
				
			||||||
 | 
					  <script type="text/javascript"><![CDATA[
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var XLINK_NS = "http://www.w3.org/1999/xlink";
 | 
				
			||||||
 | 
					var SVG_NS = "http://www.w3.org/2000/svg";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var gPhases = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var gIDCache = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var gMagPixPaths = [];     // 2D array of array-of-two <path> objects used in the pixel magnifier
 | 
				
			||||||
 | 
					var gMagWidth = 5;         // number of zoomed in pixels to show horizontally
 | 
				
			||||||
 | 
					var gMagHeight = 5;        // number of zoomed in pixels to show vertically
 | 
				
			||||||
 | 
					var gMagZoom = 16;         // size of the zoomed in pixels
 | 
				
			||||||
 | 
					var gImage1Data;           // ImageData object for the test output image
 | 
				
			||||||
 | 
					var gImage2Data;           // ImageData object for the reference image
 | 
				
			||||||
 | 
					var gFlashingPixels = [];  // array of <path> objects that should be flashed due to pixel color mismatch
 | 
				
			||||||
 | 
					var gPath = '';            // path taken from #web= and prepended to ref/snp urls
 | 
				
			||||||
 | 
					var gSelected = null;      // currently selected comparison
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function ID(id) {
 | 
				
			||||||
 | 
					  if (!(id in gIDCache))
 | 
				
			||||||
 | 
					    gIDCache[id] = document.getElementById(id);
 | 
				
			||||||
 | 
					  return gIDCache[id];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function hash_parameters() {
 | 
				
			||||||
 | 
					  var result = { };
 | 
				
			||||||
 | 
					  var params = window.location.hash.substr(1).split(/[&;]/);
 | 
				
			||||||
 | 
					  for (var i = 0; i < params.length; i++) {
 | 
				
			||||||
 | 
					    var parts = params[i].split("=");
 | 
				
			||||||
 | 
					    result[parts[0]] = unescape(unescape(parts[1]));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function load() {
 | 
				
			||||||
 | 
					  gPhases = [ ID("entry"), ID("loading"), ID("viewer") ];
 | 
				
			||||||
 | 
					  build_mag();
 | 
				
			||||||
 | 
					  var params = hash_parameters();
 | 
				
			||||||
 | 
					  if (params.log) {
 | 
				
			||||||
 | 
					    ID("logentry").value = params.log;
 | 
				
			||||||
 | 
					    log_pasted();
 | 
				
			||||||
 | 
					  } else if (params.web) {
 | 
				
			||||||
 | 
					    loadFromWeb(params.web); 
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function build_mag() {
 | 
				
			||||||
 | 
					  var mag = ID("mag");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  var r = document.createElementNS(SVG_NS, "rect");
 | 
				
			||||||
 | 
					  r.setAttribute("x", gMagZoom * -gMagWidth / 2);
 | 
				
			||||||
 | 
					  r.setAttribute("y", gMagZoom * -gMagHeight / 2);
 | 
				
			||||||
 | 
					  r.setAttribute("width", gMagZoom * gMagWidth);
 | 
				
			||||||
 | 
					  r.setAttribute("height", gMagZoom * gMagHeight);
 | 
				
			||||||
 | 
					  mag.appendChild(r);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  mag.setAttribute("transform", "translate(" + (gMagZoom * (gMagWidth / 2) + 1) + "," + (gMagZoom * (gMagHeight / 2) + 1) + ")");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (var x = 0; x < gMagWidth; x++) {
 | 
				
			||||||
 | 
					    gMagPixPaths[x] = [];
 | 
				
			||||||
 | 
					    for (var y = 0; y < gMagHeight; y++) {
 | 
				
			||||||
 | 
					      var p1 = document.createElementNS(SVG_NS, "path");
 | 
				
			||||||
 | 
					      p1.setAttribute("d", "M" + ((x - gMagWidth / 2) + 1) * gMagZoom + "," + (y - gMagHeight / 2) * gMagZoom + "h" + -gMagZoom + "v" + gMagZoom);
 | 
				
			||||||
 | 
					      p1.setAttribute("stroke", "black");
 | 
				
			||||||
 | 
					      p1.setAttribute("stroke-width", "1px");
 | 
				
			||||||
 | 
					      p1.setAttribute("fill", "#aaa");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      var p2 = document.createElementNS(SVG_NS, "path");
 | 
				
			||||||
 | 
					      p2.setAttribute("d", "M" + ((x - gMagWidth / 2) + 1) * gMagZoom + "," + (y - gMagHeight / 2) * gMagZoom + "v" + gMagZoom + "h" + -gMagZoom);
 | 
				
			||||||
 | 
					      p2.setAttribute("stroke", "black");
 | 
				
			||||||
 | 
					      p2.setAttribute("stroke-width", "1px");
 | 
				
			||||||
 | 
					      p2.setAttribute("fill", "#888");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      mag.appendChild(p1);
 | 
				
			||||||
 | 
					      mag.appendChild(p2);
 | 
				
			||||||
 | 
					      gMagPixPaths[x][y] = [p1, p2];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  var flashedOn = false;
 | 
				
			||||||
 | 
					  setInterval(function() {
 | 
				
			||||||
 | 
					    flashedOn = !flashedOn;
 | 
				
			||||||
 | 
					    flash_pixels(flashedOn);
 | 
				
			||||||
 | 
					  }, 500);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function show_phase(phaseid) {
 | 
				
			||||||
 | 
					  for (var i in gPhases) {
 | 
				
			||||||
 | 
					    var phase = gPhases[i];
 | 
				
			||||||
 | 
					    phase.style.display = (phase.id == phaseid) ? "" : "none";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (phase == "viewer")
 | 
				
			||||||
 | 
					    ID("images").style.display = "none";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function loadFromWeb(url) {
 | 
				
			||||||
 | 
					  var lastSlash = url.lastIndexOf('/');
 | 
				
			||||||
 | 
					  if (lastSlash) {
 | 
				
			||||||
 | 
					    gPath = url.substring(0, lastSlash + 1);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  var r = new XMLHttpRequest();
 | 
				
			||||||
 | 
					  r.open("GET", url);
 | 
				
			||||||
 | 
					  r.onreadystatechange = function() {
 | 
				
			||||||
 | 
					    if (r.readyState == 4) {
 | 
				
			||||||
 | 
					      process_log(r.response);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  r.send(null);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function fileentry_changed() {
 | 
				
			||||||
 | 
					  show_phase("loading");
 | 
				
			||||||
 | 
					  var input = ID("fileentry");
 | 
				
			||||||
 | 
					  var files = input.files;
 | 
				
			||||||
 | 
					  if (files.length > 0) {
 | 
				
			||||||
 | 
					    // Only handle the first file; don't handle multiple selection.
 | 
				
			||||||
 | 
					    // The parts of the log we care about are ASCII-only.  Since we
 | 
				
			||||||
 | 
					    // can ignore lines we don't care about, best to read in as
 | 
				
			||||||
 | 
					    // iso-8859-1, which guarantees we don't get decoding errors.
 | 
				
			||||||
 | 
					    var fileReader = new FileReader();
 | 
				
			||||||
 | 
					    fileReader.onload = function(e) {
 | 
				
			||||||
 | 
					      var log = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      log = e.target.result;
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
 | 
					      if (log)
 | 
				
			||||||
 | 
					        process_log(log);
 | 
				
			||||||
 | 
					      else
 | 
				
			||||||
 | 
					        show_phase("entry");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    fileReader.readAsText(files[0], "iso-8859-1");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  // So the user can process the same filename again (after
 | 
				
			||||||
 | 
					  // overwriting the log), clear the value on the form input so we
 | 
				
			||||||
 | 
					  // will always get an onchange event.
 | 
				
			||||||
 | 
					  input.value = "";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function log_pasted() {
 | 
				
			||||||
 | 
					  show_phase("loading");
 | 
				
			||||||
 | 
					  var entry = ID("logentry");
 | 
				
			||||||
 | 
					  var log = entry.value;
 | 
				
			||||||
 | 
					  entry.value = "";
 | 
				
			||||||
 | 
					  process_log(log);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var gTestItems;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function process_log(contents) {
 | 
				
			||||||
 | 
					  var lines = contents.split(/[\r\n]+/);
 | 
				
			||||||
 | 
					  gTestItems = [];
 | 
				
			||||||
 | 
					  for (var j in lines) {
 | 
				
			||||||
 | 
					    var line = lines[j];
 | 
				
			||||||
 | 
					    var match = line.match(/^(?:NEXT ERROR )?REFTEST (.*)$/);
 | 
				
			||||||
 | 
					    if (!match)
 | 
				
			||||||
 | 
					      continue;
 | 
				
			||||||
 | 
					    line = match[1];
 | 
				
			||||||
 | 
					    match = line.match(/^(TEST-PASS|TEST-UNEXPECTED-PASS|TEST-KNOWN-FAIL|TEST-UNEXPECTED-FAIL)(\(EXPECTED RANDOM\)|) \| ([^\|]+) \|(.*)/);
 | 
				
			||||||
 | 
					    if (match) {
 | 
				
			||||||
 | 
					      var state = match[1];
 | 
				
			||||||
 | 
					      var random = match[2];
 | 
				
			||||||
 | 
					      var url = match[3];
 | 
				
			||||||
 | 
					                        var extra = match[4];
 | 
				
			||||||
 | 
					      gTestItems.push(
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          pass: !state.match(/FAIL$/),
 | 
				
			||||||
 | 
					          // only one of the following three should ever be true
 | 
				
			||||||
 | 
					          unexpected: !!state.match(/^TEST-UNEXPECTED/),
 | 
				
			||||||
 | 
					          random: (random == "(EXPECTED RANDOM)"),
 | 
				
			||||||
 | 
					          skip: (extra == " (SKIP)"),
 | 
				
			||||||
 | 
					          url: url,
 | 
				
			||||||
 | 
					          images: []
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					      continue;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    match = line.match(/^  IMAGE[^:]*: (.*)$/);
 | 
				
			||||||
 | 
					    if (match) {
 | 
				
			||||||
 | 
					      var item = gTestItems[gTestItems.length - 1];
 | 
				
			||||||
 | 
					      item.images.push(match[1]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  build_viewer();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function build_viewer() {
 | 
				
			||||||
 | 
					  if (gTestItems.length == 0) {
 | 
				
			||||||
 | 
					    show_phase("entry");
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  var cell = ID("itemlist");
 | 
				
			||||||
 | 
					  while (cell.childNodes.length > 0)
 | 
				
			||||||
 | 
					    cell.removeChild(cell.childNodes[cell.childNodes.length - 1]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  var table = document.createElement("table");
 | 
				
			||||||
 | 
					  var tbody = document.createElement("tbody");
 | 
				
			||||||
 | 
					  table.appendChild(tbody);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (var i in gTestItems) {
 | 
				
			||||||
 | 
					    var item = gTestItems[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // XXX skip expected pass items until we have filtering UI
 | 
				
			||||||
 | 
					    if (item.pass && !item.unexpected)
 | 
				
			||||||
 | 
					      continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var tr = document.createElement("tr");
 | 
				
			||||||
 | 
					    var rowclass = item.pass ? "pass" : "fail";
 | 
				
			||||||
 | 
					    var td;
 | 
				
			||||||
 | 
					    var text;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    td = document.createElement("td");
 | 
				
			||||||
 | 
					    text = "";
 | 
				
			||||||
 | 
					    if (item.unexpected) { text += "!"; rowclass += " unexpected"; }
 | 
				
			||||||
 | 
					    if (item.random) { text += "R"; rowclass += " random"; }
 | 
				
			||||||
 | 
					    if (item.skip) { text += "S"; rowclass += " skip"; }
 | 
				
			||||||
 | 
					    td.appendChild(document.createTextNode(text));
 | 
				
			||||||
 | 
					    tr.appendChild(td);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    td = document.createElement("td");
 | 
				
			||||||
 | 
					    td.id = "url" + i;
 | 
				
			||||||
 | 
					    td.className = "url";
 | 
				
			||||||
 | 
					    // Only display part of URL after "/mozilla/".
 | 
				
			||||||
 | 
					    var match = item.url.match(/\/mozilla\/(.*)/);
 | 
				
			||||||
 | 
					    text = document.createTextNode(match ? match[1] : item.url);
 | 
				
			||||||
 | 
					    if (item.images.length > 0) {
 | 
				
			||||||
 | 
					      var a = document.createElement("a");
 | 
				
			||||||
 | 
					      a.href = "javascript:show_images(" + i + ")";
 | 
				
			||||||
 | 
					      a.appendChild(text);
 | 
				
			||||||
 | 
					      td.appendChild(a);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      td.appendChild(text);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    tr.appendChild(td);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tbody.appendChild(tr);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  cell.appendChild(table);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  show_phase("viewer");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function get_image_data(src, whenReady) {
 | 
				
			||||||
 | 
					  var img = new Image();
 | 
				
			||||||
 | 
					  img.onload = function() {
 | 
				
			||||||
 | 
					    var canvas = document.createElement("canvas");
 | 
				
			||||||
 | 
					    canvas.width = 800;
 | 
				
			||||||
 | 
					    canvas.height = 1000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    var ctx = canvas.getContext("2d");
 | 
				
			||||||
 | 
					    ctx.drawImage(img, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    whenReady(ctx.getImageData(0, 0, 800, 1000));
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  img.src = gPath + src;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function show_images(i) {
 | 
				
			||||||
 | 
					  if (gSelected !== null) {
 | 
				
			||||||
 | 
					    ID('url' + gSelected).classList.remove('selected');
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  gSelected = i;
 | 
				
			||||||
 | 
					  ID('url' + gSelected).classList.add('selected');
 | 
				
			||||||
 | 
					  var item = gTestItems[i];
 | 
				
			||||||
 | 
					  var cell = ID("images");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ID("image1").style.display = "";
 | 
				
			||||||
 | 
					  ID("image2").style.display = "none";
 | 
				
			||||||
 | 
					  ID("diffrect").style.display = "none";
 | 
				
			||||||
 | 
					  ID("imgcontrols").reset();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ID("image1").setAttributeNS(XLINK_NS, "xlink:href", gPath + item.images[0]);
 | 
				
			||||||
 | 
					  // Making the href be #image1 doesn't seem to work
 | 
				
			||||||
 | 
					  ID("feimage1").setAttributeNS(XLINK_NS, "xlink:href", gPath + item.images[0]);
 | 
				
			||||||
 | 
					  if (item.images.length == 1) {
 | 
				
			||||||
 | 
					    ID("imgcontrols").style.display = "none";
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    ID("imgcontrols").style.display = "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ID("image2").setAttributeNS(XLINK_NS, "xlink:href", gPath + item.images[1]);
 | 
				
			||||||
 | 
					    // Making the href be #image2 doesn't seem to work
 | 
				
			||||||
 | 
					    ID("feimage2").setAttributeNS(XLINK_NS, "xlink:href", gPath + item.images[1]);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  cell.style.display = "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  get_image_data(item.images[0], function(data) { gImage1Data = data });
 | 
				
			||||||
 | 
					  get_image_data(item.images[1], function(data) { gImage2Data = data });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function show_image(i) {
 | 
				
			||||||
 | 
					  if (i == 1) {
 | 
				
			||||||
 | 
					    ID("image1").style.display = "";
 | 
				
			||||||
 | 
					    ID("image2").style.display = "none";
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    ID("image1").style.display = "none";
 | 
				
			||||||
 | 
					    ID("image2").style.display = "";
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function show_differences(cb) {
 | 
				
			||||||
 | 
					  ID("diffrect").style.display = cb.checked ? "" : "none";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function flash_pixels(on) {
 | 
				
			||||||
 | 
					  var stroke = on ? "red" : "black";
 | 
				
			||||||
 | 
					  var strokeWidth = on ? "2px" : "1px";
 | 
				
			||||||
 | 
					  for (var i = 0; i < gFlashingPixels.length; i++) {
 | 
				
			||||||
 | 
					    gFlashingPixels[i].setAttribute("stroke", stroke);
 | 
				
			||||||
 | 
					    gFlashingPixels[i].setAttribute("stroke-width", strokeWidth);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function cursor_point(evt) {
 | 
				
			||||||
 | 
					  var m = evt.target.getScreenCTM().inverse();
 | 
				
			||||||
 | 
					  var p = ID("svg").createSVGPoint();
 | 
				
			||||||
 | 
					  p.x = evt.clientX;
 | 
				
			||||||
 | 
					  p.y = evt.clientY;
 | 
				
			||||||
 | 
					  p = p.matrixTransform(m);
 | 
				
			||||||
 | 
					  return { x: Math.floor(p.x), y: Math.floor(p.y) };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function hex2(i) {
 | 
				
			||||||
 | 
					  return (i < 16 ? "0" : "") + i.toString(16);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function canvas_pixel_as_hex(data, x, y) {
 | 
				
			||||||
 | 
					  var offset = (y * data.width + x) * 4;
 | 
				
			||||||
 | 
					  var r = data.data[offset];
 | 
				
			||||||
 | 
					  var g = data.data[offset + 1];
 | 
				
			||||||
 | 
					  var b = data.data[offset + 2];
 | 
				
			||||||
 | 
					  return "#" + hex2(r) + hex2(g) + hex2(b);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function hex_as_rgb(hex) {
 | 
				
			||||||
 | 
					  return "rgb(" + [parseInt(hex.substring(1, 3), 16), parseInt(hex.substring(3, 5), 16), parseInt(hex.substring(5, 7), 16)] + ")";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function magnify(evt) {
 | 
				
			||||||
 | 
					  var { x: x, y: y } = cursor_point(evt);
 | 
				
			||||||
 | 
					  var centerPixelColor1, centerPixelColor2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  var dx_lo = -Math.floor(gMagWidth / 2);
 | 
				
			||||||
 | 
					  var dx_hi = Math.floor(gMagWidth / 2);
 | 
				
			||||||
 | 
					  var dy_lo = -Math.floor(gMagHeight / 2);
 | 
				
			||||||
 | 
					  var dy_hi = Math.floor(gMagHeight / 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  flash_pixels(false);
 | 
				
			||||||
 | 
					  gFlashingPixels = [];
 | 
				
			||||||
 | 
					  for (var j = dy_lo; j <= dy_hi; j++) {
 | 
				
			||||||
 | 
					    for (var i = dx_lo; i <= dx_hi; i++) {
 | 
				
			||||||
 | 
					      var px = x + i;
 | 
				
			||||||
 | 
					      var py = y + j;
 | 
				
			||||||
 | 
					      var p1 = gMagPixPaths[i + dx_hi][j + dy_hi][0];
 | 
				
			||||||
 | 
					      var p2 = gMagPixPaths[i + dx_hi][j + dy_hi][1];
 | 
				
			||||||
 | 
					      if (px < 0 || py < 0 || px >= 800 || py >= 1000) {
 | 
				
			||||||
 | 
					        p1.setAttribute("fill", "#aaa");
 | 
				
			||||||
 | 
					        p2.setAttribute("fill", "#888");
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        var color1 = canvas_pixel_as_hex(gImage1Data, x + i, y + j);
 | 
				
			||||||
 | 
					        var color2 = canvas_pixel_as_hex(gImage2Data, x + i, y + j);
 | 
				
			||||||
 | 
					        p1.setAttribute("fill", color1);
 | 
				
			||||||
 | 
					        p2.setAttribute("fill", color2);
 | 
				
			||||||
 | 
					        if (color1 != color2) {
 | 
				
			||||||
 | 
					          gFlashingPixels.push(p1, p2);
 | 
				
			||||||
 | 
					          p1.parentNode.appendChild(p1);
 | 
				
			||||||
 | 
					          p2.parentNode.appendChild(p2);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (i == 0 && j == 0) {
 | 
				
			||||||
 | 
					          centerPixelColor1 = color1;
 | 
				
			||||||
 | 
					          centerPixelColor2 = color2;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  flash_pixels(true);
 | 
				
			||||||
 | 
					  show_pixelinfo(x, y, centerPixelColor1, hex_as_rgb(centerPixelColor1), centerPixelColor2, hex_as_rgb(centerPixelColor2));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function show_pixelinfo(x, y, pix1rgb, pix1hex, pix2rgb, pix2hex) {
 | 
				
			||||||
 | 
					  var pixelinfo = ID("pixelinfo");
 | 
				
			||||||
 | 
					  ID("coords").textContent = [x, y];
 | 
				
			||||||
 | 
					  ID("pix1hex").textContent = pix1hex;
 | 
				
			||||||
 | 
					  ID("pix1rgb").textContent = pix1rgb;
 | 
				
			||||||
 | 
					  ID("pix2hex").textContent = pix2hex;
 | 
				
			||||||
 | 
					  ID("pix2rgb").textContent = pix2rgb;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					window.addEventListener('keydown', function keydown(event) {
 | 
				
			||||||
 | 
					  if (event.which === 84) {
 | 
				
			||||||
 | 
					    // 't' switch test/ref images
 | 
				
			||||||
 | 
					    var val = 0;
 | 
				
			||||||
 | 
					    if (document.querySelector('input[name="which"][value="0"]:checked')) {
 | 
				
			||||||
 | 
					      val = 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    document.querySelector('input[name="which"][value="' + val + '"]').click();
 | 
				
			||||||
 | 
					  } else if (event.which === 78 || event.which === 80) {
 | 
				
			||||||
 | 
					    // 'n' next image, 'p' previous image
 | 
				
			||||||
 | 
					    var select = gSelected;
 | 
				
			||||||
 | 
					    if (gSelected === null) {
 | 
				
			||||||
 | 
					      select = 0;
 | 
				
			||||||
 | 
					    } else if (event.which === 78) {
 | 
				
			||||||
 | 
					      select++;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      select--;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    var length = gTestItems.length;
 | 
				
			||||||
 | 
					    select = select < 0 ? length - 1 : select >= length ? 0 : select;
 | 
				
			||||||
 | 
					    show_images(select);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ]]></script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					<body onload="load()">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div id="entry">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<h1>Reftest analyzer: load reftest log</h1>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<p>Either paste your log into this textarea:<br />
 | 
				
			||||||
 | 
					<textarea cols="80" rows="10" id="logentry"/><br/>
 | 
				
			||||||
 | 
					<input type="button" value="Process pasted log" onclick="log_pasted()" /></p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<p>... or load it from a file:<br/>
 | 
				
			||||||
 | 
					<input type="file" id="fileentry" onchange="fileentry_changed()" />
 | 
				
			||||||
 | 
					</p>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div id="loading" style="display:none">Loading log...</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<div id="viewer" style="display:none">
 | 
				
			||||||
 | 
					  <div id="pixelarea">
 | 
				
			||||||
 | 
					    <div id="pixelinfo">
 | 
				
			||||||
 | 
					      <table>
 | 
				
			||||||
 | 
					        <tbody>
 | 
				
			||||||
 | 
					          <tr><th>Pixel at:</th><td colspan="2" id="coords"/></tr>
 | 
				
			||||||
 | 
					          <tr><th>Test:</th><td id="pix1rgb"></td><td id="pix1hex"></td></tr>
 | 
				
			||||||
 | 
					          <tr><th>Reference:</th><td id="pix2rgb"></td><td id="pix2hex"></td></tr>
 | 
				
			||||||
 | 
					        </tbody>
 | 
				
			||||||
 | 
					      </table>
 | 
				
			||||||
 | 
					      <div>
 | 
				
			||||||
 | 
					        <div id="pixelhint">★
 | 
				
			||||||
 | 
					          <div>
 | 
				
			||||||
 | 
					            <p>Move the mouse over the reftest image on the right to show
 | 
				
			||||||
 | 
					            magnified pixels on the left.  The color information above is for
 | 
				
			||||||
 | 
					            the pixel centered in the magnified view.</p>
 | 
				
			||||||
 | 
					            <p>Image 1 is shown in the upper triangle of each pixel and Image 2
 | 
				
			||||||
 | 
					            is shown in the lower triangle.</p>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    <div id="magnification">
 | 
				
			||||||
 | 
					      <svg xmlns="http://www.w3.org/2000/svg" width="84" height="84" shape-rendering="optimizeSpeed">
 | 
				
			||||||
 | 
					        <g id="mag"/>
 | 
				
			||||||
 | 
					      </svg>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					  <div id="itemlist"></div>
 | 
				
			||||||
 | 
					  <div id="images" style="display:none">
 | 
				
			||||||
 | 
					    <form id="imgcontrols">
 | 
				
			||||||
 | 
					    <label><input type="radio" name="which" value="0" onchange="show_image(1)" checked="checked" />Test</label>
 | 
				
			||||||
 | 
					    <label><input type="radio" name="which" value="1" onchange="show_image(2)" />Reference</label>
 | 
				
			||||||
 | 
					    <label><input type="checkbox" onchange="show_differences(this)" />Circle differences</label>
 | 
				
			||||||
 | 
					    </form>
 | 
				
			||||||
 | 
					    <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="800px" height="1000px" viewbox="0 0 800 1000" id="svg">
 | 
				
			||||||
 | 
					      <defs>
 | 
				
			||||||
 | 
					        <!-- use sRGB to avoid loss of data -->
 | 
				
			||||||
 | 
					        <filter id="showDifferences" x="0%" y="0%" width="100%" height="100%"
 | 
				
			||||||
 | 
					                style="color-interpolation-filters: sRGB">
 | 
				
			||||||
 | 
					          <feImage id="feimage1" result="img1" xlink:href="#image1" />
 | 
				
			||||||
 | 
					          <feImage id="feimage2" result="img2" xlink:href="#image2" />
 | 
				
			||||||
 | 
					          <!-- inv1 and inv2 are the images with RGB inverted -->
 | 
				
			||||||
 | 
					          <feComponentTransfer result="inv1" in="img1">
 | 
				
			||||||
 | 
					            <feFuncR type="linear" slope="-1" intercept="1" />
 | 
				
			||||||
 | 
					            <feFuncG type="linear" slope="-1" intercept="1" />
 | 
				
			||||||
 | 
					            <feFuncB type="linear" slope="-1" intercept="1" />
 | 
				
			||||||
 | 
					          </feComponentTransfer>
 | 
				
			||||||
 | 
					          <feComponentTransfer result="inv2" in="img2">
 | 
				
			||||||
 | 
					            <feFuncR type="linear" slope="-1" intercept="1" />
 | 
				
			||||||
 | 
					            <feFuncG type="linear" slope="-1" intercept="1" />
 | 
				
			||||||
 | 
					            <feFuncB type="linear" slope="-1" intercept="1" />
 | 
				
			||||||
 | 
					          </feComponentTransfer>
 | 
				
			||||||
 | 
					          <!-- w1 will have non-white pixels anywhere that img2
 | 
				
			||||||
 | 
					               is brighter than img1, and w2 for the reverse.
 | 
				
			||||||
 | 
					               It would be nice not to have to go through these
 | 
				
			||||||
 | 
					               intermediate states, but feComposite
 | 
				
			||||||
 | 
					               type="arithmetic" can't transform the RGB channels
 | 
				
			||||||
 | 
					               and leave the alpha channel untouched. -->
 | 
				
			||||||
 | 
					          <feComposite result="w1" in="img1" in2="inv2" operator="arithmetic" k2="1" k3="1" />
 | 
				
			||||||
 | 
					          <feComposite result="w2" in="img2" in2="inv1" operator="arithmetic" k2="1" k3="1" />
 | 
				
			||||||
 | 
					          <!-- c1 will have non-black pixels anywhere that img2
 | 
				
			||||||
 | 
					               is brighter than img1, and c2 for the reverse -->
 | 
				
			||||||
 | 
					          <feComponentTransfer result="c1" in="w1">
 | 
				
			||||||
 | 
					            <feFuncR type="linear" slope="-1" intercept="1" />
 | 
				
			||||||
 | 
					            <feFuncG type="linear" slope="-1" intercept="1" />
 | 
				
			||||||
 | 
					            <feFuncB type="linear" slope="-1" intercept="1" />
 | 
				
			||||||
 | 
					          </feComponentTransfer>
 | 
				
			||||||
 | 
					          <feComponentTransfer result="c2" in="w2">
 | 
				
			||||||
 | 
					            <feFuncR type="linear" slope="-1" intercept="1" />
 | 
				
			||||||
 | 
					            <feFuncG type="linear" slope="-1" intercept="1" />
 | 
				
			||||||
 | 
					            <feFuncB type="linear" slope="-1" intercept="1" />
 | 
				
			||||||
 | 
					          </feComponentTransfer>
 | 
				
			||||||
 | 
					          <!-- c will be nonblack (and fully on) for every pixel+component where there are differences -->
 | 
				
			||||||
 | 
					          <feComposite result="c" in="c1" in2="c2" operator="arithmetic" k2="255" k3="255" />
 | 
				
			||||||
 | 
					          <!-- a will be opaque for every pixel with differences and transparent for all others -->
 | 
				
			||||||
 | 
					          <feColorMatrix result="a" type="matrix" values="0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  1 1 1 0 0" />
 | 
				
			||||||
 | 
					          
 | 
				
			||||||
 | 
					          <!-- a, dilated by 4 pixels -->
 | 
				
			||||||
 | 
					          <feMorphology result="dila4" in="a" operator="dilate" radius="4" />
 | 
				
			||||||
 | 
					          <!-- a, dilated by 1 pixel -->
 | 
				
			||||||
 | 
					          <feMorphology result="dila1" in="a" operator="dilate" radius="1" />
 | 
				
			||||||
 | 
					          
 | 
				
			||||||
 | 
					          <!-- all the pixels in the 3-pixel dilation of a but not in the 1-pixel dilation of a, to highlight the diffs -->
 | 
				
			||||||
 | 
					          <feComposite result="highlight" in="dila4" in2="dila1" operator="out" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          <feFlood result="red" flood-color="red" />
 | 
				
			||||||
 | 
					          <feComposite result="redhighlight" in="red" in2="highlight" operator="in" />
 | 
				
			||||||
 | 
					          <feFlood result="black" flood-color="black" flood-opacity="0.5" />
 | 
				
			||||||
 | 
					          <feMerge>
 | 
				
			||||||
 | 
					            <feMergeNode in="black" />
 | 
				
			||||||
 | 
					            <feMergeNode in="redhighlight" />
 | 
				
			||||||
 | 
					          </feMerge>
 | 
				
			||||||
 | 
					        </filter>
 | 
				
			||||||
 | 
					      </defs>
 | 
				
			||||||
 | 
					      <g onmousemove="magnify(evt)">
 | 
				
			||||||
 | 
					        <image x="0" y="0" width="100%" height="100%" id="image1" />
 | 
				
			||||||
 | 
					        <image x="0" y="0" width="100%" height="100%" id="image2" />
 | 
				
			||||||
 | 
					      </g>
 | 
				
			||||||
 | 
					      <rect id="diffrect" filter="url(#showDifferences)" pointer-events="none" x="0" y="0" width="100%" height="100%" />
 | 
				
			||||||
 | 
					    </svg>
 | 
				
			||||||
 | 
					  </div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
							
								
								
									
										954
									
								
								public/vendor/pdfjs/test/test.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										954
									
								
								public/vendor/pdfjs/test/test.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,954 @@
 | 
				
			|||||||
 | 
					# Copyright 2012 Mozilla Foundation
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					# you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					# You may obtain a copy of the License at
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#     http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					# distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					# See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					# limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import json, platform, os, shutil, sys, subprocess, tempfile, threading
 | 
				
			||||||
 | 
					import time, urllib, urllib2, hashlib, re, base64, uuid, socket, errno
 | 
				
			||||||
 | 
					import traceback
 | 
				
			||||||
 | 
					from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
 | 
				
			||||||
 | 
					from SocketServer import ThreadingMixIn
 | 
				
			||||||
 | 
					from optparse import OptionParser
 | 
				
			||||||
 | 
					from urlparse import urlparse, parse_qs
 | 
				
			||||||
 | 
					from threading import Lock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					USAGE_EXAMPLE = "%prog"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# The local web server uses the git repo as the document root.
 | 
				
			||||||
 | 
					DOC_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__),".."))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GIT_CLONE_CHECK = True
 | 
				
			||||||
 | 
					DEFAULT_MANIFEST_FILE = 'test_manifest.json'
 | 
				
			||||||
 | 
					EQLOG_FILE = 'eq.log'
 | 
				
			||||||
 | 
					BROWSERLOG_FILE = 'browser.log'
 | 
				
			||||||
 | 
					REFDIR = 'ref'
 | 
				
			||||||
 | 
					TEST_SNAPSHOTS = 'test_snapshots'
 | 
				
			||||||
 | 
					TMPDIR = 'tmp'
 | 
				
			||||||
 | 
					VERBOSE = False
 | 
				
			||||||
 | 
					BROWSER_TIMEOUT = 120
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SERVER_HOST = "localhost"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					lock = Lock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TestOptions(OptionParser):
 | 
				
			||||||
 | 
					    def __init__(self, **kwargs):
 | 
				
			||||||
 | 
					        OptionParser.__init__(self, **kwargs)
 | 
				
			||||||
 | 
					        self.add_option("-m", "--masterMode", action="store_true", dest="masterMode",
 | 
				
			||||||
 | 
					                        help="Run the script in master mode.", default=False)
 | 
				
			||||||
 | 
					        self.add_option("--noPrompts", action="store_true", dest="noPrompts",
 | 
				
			||||||
 | 
					                        help="Uses default answers (intended for CLOUD TESTS only!).", default=False)
 | 
				
			||||||
 | 
					        self.add_option("--manifestFile", action="store", type="string", dest="manifestFile",
 | 
				
			||||||
 | 
					                        help="A JSON file in the form of test_manifest.json (the default).")
 | 
				
			||||||
 | 
					        self.add_option("-b", "--browser", action="store", type="string", dest="browser",
 | 
				
			||||||
 | 
					                        help="The path to a single browser (right now, only Firefox is supported).")
 | 
				
			||||||
 | 
					        self.add_option("--browserManifestFile", action="store", type="string",
 | 
				
			||||||
 | 
					                        dest="browserManifestFile",
 | 
				
			||||||
 | 
					                        help="A JSON file in the form of those found in resources/browser_manifests")
 | 
				
			||||||
 | 
					        self.add_option("--reftest", action="store_true", dest="reftest",
 | 
				
			||||||
 | 
					                        help="Automatically start reftest showing comparison test failures, if there are any.",
 | 
				
			||||||
 | 
					                        default=False)
 | 
				
			||||||
 | 
					        self.add_option("--port", action="store", dest="port", type="int",
 | 
				
			||||||
 | 
					                        help="The port the HTTP server should listen on.", default=8080)
 | 
				
			||||||
 | 
					        self.add_option("--unitTest", action="store_true", dest="unitTest",
 | 
				
			||||||
 | 
					                        help="Run the unit tests.", default=False)
 | 
				
			||||||
 | 
					        self.add_option("--fontTest", action="store_true", dest="fontTest",
 | 
				
			||||||
 | 
					                        help="Run the font tests.", default=False)
 | 
				
			||||||
 | 
					        self.add_option("--noDownload", action="store_true", dest="noDownload",
 | 
				
			||||||
 | 
					                        help="Skips test PDFs downloading.", default=False)
 | 
				
			||||||
 | 
					        self.add_option("--statsFile", action="store", dest="statsFile", type="string",
 | 
				
			||||||
 | 
					                        help="The file where to store stats.", default=None)
 | 
				
			||||||
 | 
					        self.add_option("--statsDelay", action="store", dest="statsDelay", type="int",
 | 
				
			||||||
 | 
					                        help="The amount of time in milliseconds the browser should wait before starting stats.", default=10000)
 | 
				
			||||||
 | 
					        self.set_usage(USAGE_EXAMPLE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def verifyOptions(self, options):
 | 
				
			||||||
 | 
					        if options.reftest and (options.unitTest or options.fontTest):
 | 
				
			||||||
 | 
					            self.error("--reftest and --unitTest/--fontTest must not be specified at the same time.")
 | 
				
			||||||
 | 
					        if options.masterMode and options.manifestFile:
 | 
				
			||||||
 | 
					            self.error("--masterMode and --manifestFile must not be specified at the same time.")
 | 
				
			||||||
 | 
					        if not options.manifestFile:
 | 
				
			||||||
 | 
					            options.manifestFile = DEFAULT_MANIFEST_FILE
 | 
				
			||||||
 | 
					        if options.browser and options.browserManifestFile:
 | 
				
			||||||
 | 
					            print "Warning: ignoring browser argument since manifest file was also supplied"
 | 
				
			||||||
 | 
					        if not options.browser and not options.browserManifestFile:
 | 
				
			||||||
 | 
					            print "Starting server on port %s." % options.port
 | 
				
			||||||
 | 
					        if not options.statsFile:
 | 
				
			||||||
 | 
					            options.statsDelay = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return options
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def prompt(question):
 | 
				
			||||||
 | 
					    '''Return True iff the user answered "yes" to |question|.'''
 | 
				
			||||||
 | 
					    inp = raw_input(question +' [yes/no] > ')
 | 
				
			||||||
 | 
					    return inp == 'yes'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MIMEs = {
 | 
				
			||||||
 | 
					    '.css': 'text/css',
 | 
				
			||||||
 | 
					    '.html': 'text/html',
 | 
				
			||||||
 | 
					    '.js': 'application/javascript',
 | 
				
			||||||
 | 
					    '.json': 'application/json',
 | 
				
			||||||
 | 
					    '.svg': 'image/svg+xml',
 | 
				
			||||||
 | 
					    '.pdf': 'application/pdf',
 | 
				
			||||||
 | 
					    '.xhtml': 'application/xhtml+xml',
 | 
				
			||||||
 | 
					    '.gif': 'image/gif',
 | 
				
			||||||
 | 
					    '.ico': 'image/x-icon',
 | 
				
			||||||
 | 
					    '.png': 'image/png',
 | 
				
			||||||
 | 
					    '.log': 'text/plain',
 | 
				
			||||||
 | 
					    '.properties': 'text/plain'
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class State:
 | 
				
			||||||
 | 
					    browsers = [ ]
 | 
				
			||||||
 | 
					    manifest = { }
 | 
				
			||||||
 | 
					    taskResults = { }
 | 
				
			||||||
 | 
					    remaining = { }
 | 
				
			||||||
 | 
					    results = { }
 | 
				
			||||||
 | 
					    done = False
 | 
				
			||||||
 | 
					    numErrors = 0
 | 
				
			||||||
 | 
					    numEqFailures = 0
 | 
				
			||||||
 | 
					    numEqNoSnapshot = 0
 | 
				
			||||||
 | 
					    numFBFFailures = 0
 | 
				
			||||||
 | 
					    numLoadFailures = 0
 | 
				
			||||||
 | 
					    eqLog = None
 | 
				
			||||||
 | 
					    saveStats = False
 | 
				
			||||||
 | 
					    stats = [ ]
 | 
				
			||||||
 | 
					    lastPost = { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class UnitTestState:
 | 
				
			||||||
 | 
					    browsers = [ ]
 | 
				
			||||||
 | 
					    browsersRunning = 0
 | 
				
			||||||
 | 
					    lastPost = { }
 | 
				
			||||||
 | 
					    numErrors = 0
 | 
				
			||||||
 | 
					    numRun = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Result:
 | 
				
			||||||
 | 
					    def __init__(self, snapshot, failure, page):
 | 
				
			||||||
 | 
					        self.snapshot = snapshot
 | 
				
			||||||
 | 
					        self.failure = failure
 | 
				
			||||||
 | 
					        self.page = page
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TestServer(ThreadingMixIn, HTTPServer):
 | 
				
			||||||
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TestHandlerBase(BaseHTTPRequestHandler):
 | 
				
			||||||
 | 
					    # Disable annoying noise by default
 | 
				
			||||||
 | 
					    def log_request(code=0, size=0):
 | 
				
			||||||
 | 
					        if VERBOSE:
 | 
				
			||||||
 | 
					            BaseHTTPRequestHandler.log_request(code, size)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def handle_one_request(self):
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            BaseHTTPRequestHandler.handle_one_request(self)
 | 
				
			||||||
 | 
					        except socket.error, v:
 | 
				
			||||||
 | 
					            if v[0] == errno.ECONNRESET:
 | 
				
			||||||
 | 
					                # Ignoring connection reset by peer exceptions
 | 
				
			||||||
 | 
					                if VERBOSE:
 | 
				
			||||||
 | 
					                    print 'Detected connection reset'
 | 
				
			||||||
 | 
					            elif v[0] == errno.EPIPE:
 | 
				
			||||||
 | 
					                if VERBOSE:
 | 
				
			||||||
 | 
					                    print 'Detected remote peer disconnected'
 | 
				
			||||||
 | 
					            elif v[0] == 10053:
 | 
				
			||||||
 | 
					                if VERBOSE:
 | 
				
			||||||
 | 
					                    print 'An established connection was aborted by the' \
 | 
				
			||||||
 | 
					                          ' software in your host machine'
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                raise
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def finish(self,*args,**kw):
 | 
				
			||||||
 | 
					        # From http://stackoverflow.com/a/14355079/1834797
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            if not self.wfile.closed:
 | 
				
			||||||
 | 
					                self.wfile.flush()
 | 
				
			||||||
 | 
					                self.wfile.close()
 | 
				
			||||||
 | 
					        except socket.error:
 | 
				
			||||||
 | 
					            pass
 | 
				
			||||||
 | 
					        self.rfile.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def sendFile(self, path, ext):
 | 
				
			||||||
 | 
					        self.send_response(200)
 | 
				
			||||||
 | 
					        self.send_header("Accept-Ranges", "bytes")
 | 
				
			||||||
 | 
					        self.send_header("Content-Type", MIMEs[ext])
 | 
				
			||||||
 | 
					        self.send_header("Content-Length", os.path.getsize(path))
 | 
				
			||||||
 | 
					        self.end_headers()
 | 
				
			||||||
 | 
					        with open(path, "rb") as f:
 | 
				
			||||||
 | 
					            self.wfile.write(f.read())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def sendFileRange(self, path, ext, start, end):
 | 
				
			||||||
 | 
					        file_len = os.path.getsize(path)
 | 
				
			||||||
 | 
					        if (end is None) or (file_len < end):
 | 
				
			||||||
 | 
					          end = file_len
 | 
				
			||||||
 | 
					        if (file_len < start) or (end <= start):
 | 
				
			||||||
 | 
					          self.send_error(416)
 | 
				
			||||||
 | 
					          return
 | 
				
			||||||
 | 
					        chunk_len = end - start
 | 
				
			||||||
 | 
					        time.sleep(chunk_len / 1000000.0)
 | 
				
			||||||
 | 
					        self.send_response(206)
 | 
				
			||||||
 | 
					        self.send_header("Accept-Ranges", "bytes")
 | 
				
			||||||
 | 
					        self.send_header("Content-Type", MIMEs[ext])
 | 
				
			||||||
 | 
					        self.send_header("Content-Length", chunk_len)
 | 
				
			||||||
 | 
					        self.send_header("Content-Range", 'bytes ' + str(start) + '-' + str(end - 1) + '/' + str(file_len))
 | 
				
			||||||
 | 
					        self.end_headers()
 | 
				
			||||||
 | 
					        with open(path, "rb") as f:
 | 
				
			||||||
 | 
					            f.seek(start)
 | 
				
			||||||
 | 
					            self.wfile.write(f.read(chunk_len))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def do_GET(self):
 | 
				
			||||||
 | 
					        url = urlparse(self.path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Ignore query string
 | 
				
			||||||
 | 
					        path, _ = urllib.unquote_plus(url.path), url.query
 | 
				
			||||||
 | 
					        path = os.path.abspath(os.path.realpath(DOC_ROOT + os.sep + path))
 | 
				
			||||||
 | 
					        prefix = os.path.commonprefix(( path, DOC_ROOT ))
 | 
				
			||||||
 | 
					        _, ext = os.path.splitext(path.lower())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if url.path == "/favicon.ico":
 | 
				
			||||||
 | 
					            self.sendFile(os.path.join(DOC_ROOT, "test", "resources", "favicon.ico"), ext)
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if os.path.isdir(path):
 | 
				
			||||||
 | 
					            self.sendIndex(url.path, url.query)
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if not (prefix == DOC_ROOT
 | 
				
			||||||
 | 
					                and os.path.isfile(path)
 | 
				
			||||||
 | 
					                and ext in MIMEs):
 | 
				
			||||||
 | 
					            print path
 | 
				
			||||||
 | 
					            self.send_error(404)
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if 'Range' in self.headers:
 | 
				
			||||||
 | 
					            range_re = re.compile(r"^bytes=(\d+)\-(\d+)?")
 | 
				
			||||||
 | 
					            parsed_range = range_re.search(self.headers.getheader("Range"))
 | 
				
			||||||
 | 
					            if parsed_range is None:
 | 
				
			||||||
 | 
					                self.send_error(501)
 | 
				
			||||||
 | 
					                return
 | 
				
			||||||
 | 
					            if VERBOSE:
 | 
				
			||||||
 | 
					                print 'Range requested %s - %s: %s' % (
 | 
				
			||||||
 | 
					                    parsed_range.group(1), parsed_range.group(2))
 | 
				
			||||||
 | 
					            start = int(parsed_range.group(1))
 | 
				
			||||||
 | 
					            if parsed_range.group(2) is None:
 | 
				
			||||||
 | 
					                self.sendFileRange(path, ext, start, None)
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                end = int(parsed_range.group(2)) + 1
 | 
				
			||||||
 | 
					                self.sendFileRange(path, ext, start, end)
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.sendFile(path, ext)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class UnitTestHandler(TestHandlerBase):
 | 
				
			||||||
 | 
					    def sendIndex(self, path, query):
 | 
				
			||||||
 | 
					        print "send index"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def translateFont(self, base64Data):
 | 
				
			||||||
 | 
					        self.send_response(200)
 | 
				
			||||||
 | 
					        self.send_header("Content-Type", "text/xml")
 | 
				
			||||||
 | 
					        self.end_headers()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        data = base64.b64decode(base64Data)
 | 
				
			||||||
 | 
					        taskId = str(uuid.uuid4())
 | 
				
			||||||
 | 
					        fontPath = 'ttx/' + taskId + '.otf'
 | 
				
			||||||
 | 
					        resultPath = 'ttx/' + taskId + '.ttx'
 | 
				
			||||||
 | 
					        with open(fontPath, "wb") as f:
 | 
				
			||||||
 | 
					            f.write(data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # When fontTools used directly, we need to snif ttx file
 | 
				
			||||||
 | 
					        # to check what version of python is used
 | 
				
			||||||
 | 
					        ttxPath = ''
 | 
				
			||||||
 | 
					        for path in os.environ["PATH"].split(os.pathsep):
 | 
				
			||||||
 | 
					            if os.path.isfile(path + os.sep + "ttx"):
 | 
				
			||||||
 | 
					                ttxPath = path + os.sep + "ttx"
 | 
				
			||||||
 | 
					                break
 | 
				
			||||||
 | 
					        if ttxPath == '':
 | 
				
			||||||
 | 
					            self.wfile.write("<error>TTX was not found</error>")
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ttxRunner = ''
 | 
				
			||||||
 | 
					        with open(ttxPath, "r") as f:
 | 
				
			||||||
 | 
					            firstLine = f.readline()
 | 
				
			||||||
 | 
					            if firstLine[:2] == '#!' and firstLine.find('python') > -1:
 | 
				
			||||||
 | 
					              ttxRunner = firstLine[2:].strip()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        with open(os.devnull, "w") as fnull:
 | 
				
			||||||
 | 
					            if ttxRunner != '':
 | 
				
			||||||
 | 
					                result = subprocess.call([ttxRunner, ttxPath, fontPath], stdout = fnull)
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                result = subprocess.call([ttxPath, fontPath], stdout = fnull)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        os.remove(fontPath)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if not os.path.isfile(resultPath):
 | 
				
			||||||
 | 
					            self.wfile.write("<error>Output was not generated</error>")
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        with open(resultPath, "rb") as f:
 | 
				
			||||||
 | 
					            self.wfile.write(f.read())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        os.remove(resultPath)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def do_POST(self):
 | 
				
			||||||
 | 
					        with lock:
 | 
				
			||||||
 | 
					            url = urlparse(self.path)
 | 
				
			||||||
 | 
					            numBytes = int(self.headers['Content-Length'])
 | 
				
			||||||
 | 
					            content = self.rfile.read(numBytes)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # Process special utility requests
 | 
				
			||||||
 | 
					            if url.path == '/ttx':
 | 
				
			||||||
 | 
					                self.translateFont(content)
 | 
				
			||||||
 | 
					                return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            self.send_response(200)
 | 
				
			||||||
 | 
					            self.send_header('Content-Type', 'text/plain')
 | 
				
			||||||
 | 
					            self.end_headers()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            result = json.loads(content)
 | 
				
			||||||
 | 
					            browser = result['browser']
 | 
				
			||||||
 | 
					            UnitTestState.lastPost[browser] = int(time.time())
 | 
				
			||||||
 | 
					            if url.path == "/tellMeToQuit":
 | 
				
			||||||
 | 
					                tellAppToQuit(url.path, url.query)
 | 
				
			||||||
 | 
					                UnitTestState.browsersRunning -= 1
 | 
				
			||||||
 | 
					                UnitTestState.lastPost[browser] = None
 | 
				
			||||||
 | 
					                return
 | 
				
			||||||
 | 
					            elif url.path == '/info':
 | 
				
			||||||
 | 
					                print result['message']
 | 
				
			||||||
 | 
					            elif url.path == '/submit_task_results':
 | 
				
			||||||
 | 
					                status, description = result['status'], result['description']
 | 
				
			||||||
 | 
					                UnitTestState.numRun += 1
 | 
				
			||||||
 | 
					                if status == 'TEST-UNEXPECTED-FAIL':
 | 
				
			||||||
 | 
					                    UnitTestState.numErrors += 1
 | 
				
			||||||
 | 
					                message = status + ' | ' + description + ' | in ' + browser
 | 
				
			||||||
 | 
					                if 'error' in result:
 | 
				
			||||||
 | 
					                    message += ' | ' + result['error']
 | 
				
			||||||
 | 
					                print message
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                print 'Error: uknown action' + url.path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class PDFTestHandler(TestHandlerBase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def sendIndex(self, path, query):
 | 
				
			||||||
 | 
					        if not path.endswith("/"):
 | 
				
			||||||
 | 
					          # we need trailing slash
 | 
				
			||||||
 | 
					          self.send_response(301)
 | 
				
			||||||
 | 
					          redirectLocation = path + "/"
 | 
				
			||||||
 | 
					          if query:
 | 
				
			||||||
 | 
					            redirectLocation += "?" + query
 | 
				
			||||||
 | 
					          self.send_header("Location",  redirectLocation)
 | 
				
			||||||
 | 
					          self.end_headers()
 | 
				
			||||||
 | 
					          return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.send_response(200)
 | 
				
			||||||
 | 
					        self.send_header("Content-Type", "text/html")
 | 
				
			||||||
 | 
					        self.end_headers()
 | 
				
			||||||
 | 
					        if query == "frame":
 | 
				
			||||||
 | 
					          self.wfile.write("<html><frameset cols=*,200><frame name=pdf>" +
 | 
				
			||||||
 | 
					            "<frame src='" + path + "'></frameset></html>")
 | 
				
			||||||
 | 
					          return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        location = os.path.abspath(os.path.realpath(DOC_ROOT + os.sep + path))
 | 
				
			||||||
 | 
					        self.wfile.write("<html><body><h1>PDFs of " + path + "</h1>\n")
 | 
				
			||||||
 | 
					        for filename in os.listdir(location):
 | 
				
			||||||
 | 
					          if filename.lower().endswith('.pdf'):
 | 
				
			||||||
 | 
					            self.wfile.write("<a href='/web/viewer.html?file=" +
 | 
				
			||||||
 | 
					              urllib.quote_plus(path + filename, '/') + "' target=pdf>" +
 | 
				
			||||||
 | 
					              filename + "</a><br>\n")
 | 
				
			||||||
 | 
					        self.wfile.write("</body></html>")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def do_POST(self):
 | 
				
			||||||
 | 
					        with lock:
 | 
				
			||||||
 | 
					            numBytes = int(self.headers['Content-Length'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            self.send_response(200)
 | 
				
			||||||
 | 
					            self.send_header('Content-Type', 'text/plain')
 | 
				
			||||||
 | 
					            self.end_headers()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            url = urlparse(self.path)
 | 
				
			||||||
 | 
					            if url.path == "/tellMeToQuit":
 | 
				
			||||||
 | 
					                tellAppToQuit(url.path, url.query)
 | 
				
			||||||
 | 
					                return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            result = json.loads(self.rfile.read(numBytes))
 | 
				
			||||||
 | 
					            browser = result['browser']
 | 
				
			||||||
 | 
					            State.lastPost[browser] = int(time.time())
 | 
				
			||||||
 | 
					            if url.path == "/info":
 | 
				
			||||||
 | 
					                print result['message']
 | 
				
			||||||
 | 
					                return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            id = result['id']
 | 
				
			||||||
 | 
					            failure = result['failure']
 | 
				
			||||||
 | 
					            round = result['round']
 | 
				
			||||||
 | 
					            page = result['page']
 | 
				
			||||||
 | 
					            snapshot = result['snapshot']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            taskResults = State.taskResults[browser][id]
 | 
				
			||||||
 | 
					            taskResults[round].append(Result(snapshot, failure, page))
 | 
				
			||||||
 | 
					            if State.saveStats:
 | 
				
			||||||
 | 
					                stat = {
 | 
				
			||||||
 | 
					                    'browser': browser,
 | 
				
			||||||
 | 
					                    'pdf': id,
 | 
				
			||||||
 | 
					                    'page': page,
 | 
				
			||||||
 | 
					                    'round': round,
 | 
				
			||||||
 | 
					                    'stats': result['stats']
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                State.stats.append(stat)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            def isTaskDone():
 | 
				
			||||||
 | 
					                last_page_num = result['lastPageNum']
 | 
				
			||||||
 | 
					                rounds = State.manifest[id]['rounds']
 | 
				
			||||||
 | 
					                for round in range(0,rounds):
 | 
				
			||||||
 | 
					                    if not taskResults[round]:
 | 
				
			||||||
 | 
					                        return False
 | 
				
			||||||
 | 
					                    latest_page = taskResults[round][-1]
 | 
				
			||||||
 | 
					                    if not latest_page.page == last_page_num:
 | 
				
			||||||
 | 
					                        return False
 | 
				
			||||||
 | 
					                return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if isTaskDone():
 | 
				
			||||||
 | 
					                # sort the results since they sometimes come in out of order
 | 
				
			||||||
 | 
					                for results in taskResults:
 | 
				
			||||||
 | 
					                    results.sort(key=lambda result: result.page)
 | 
				
			||||||
 | 
					                check(State.manifest[id], taskResults, browser,
 | 
				
			||||||
 | 
					                    self.server.masterMode)
 | 
				
			||||||
 | 
					                # Please oh please GC this ...
 | 
				
			||||||
 | 
					                del State.taskResults[browser][id]
 | 
				
			||||||
 | 
					                State.remaining[browser] -= 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                checkIfDone()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def checkIfDone():
 | 
				
			||||||
 | 
					    State.done = True
 | 
				
			||||||
 | 
					    for key in State.remaining:
 | 
				
			||||||
 | 
					        if State.remaining[key] != 0:
 | 
				
			||||||
 | 
					            State.done = False
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Applescript hack to quit Chrome on Mac
 | 
				
			||||||
 | 
					def tellAppToQuit(path, query):
 | 
				
			||||||
 | 
					    if platform.system() != "Darwin":
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					    d = parse_qs(query)
 | 
				
			||||||
 | 
					    path = d['path'][0]
 | 
				
			||||||
 | 
					    cmd = """osascript<<END
 | 
				
			||||||
 | 
					tell application "%s"
 | 
				
			||||||
 | 
					quit
 | 
				
			||||||
 | 
					end tell
 | 
				
			||||||
 | 
					END""" % path
 | 
				
			||||||
 | 
					    os.system(cmd)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class BaseBrowserCommand(object):
 | 
				
			||||||
 | 
					    def __init__(self, browserRecord):
 | 
				
			||||||
 | 
					        self.name = browserRecord["name"]
 | 
				
			||||||
 | 
					        self.path = browserRecord["path"]
 | 
				
			||||||
 | 
					        self.tempDir = None
 | 
				
			||||||
 | 
					        self.process = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if platform.system() == "Darwin" and (self.path.endswith(".app") or self.path.endswith(".app/")):
 | 
				
			||||||
 | 
					            self._fixupMacPath()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if not os.path.exists(self.path):
 | 
				
			||||||
 | 
					            raise Exception("Path to browser '%s' does not exist." % self.path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def setup(self):
 | 
				
			||||||
 | 
					        self.tempDir = tempfile.mkdtemp()
 | 
				
			||||||
 | 
					        self.profileDir = os.path.join(self.tempDir, "profile")
 | 
				
			||||||
 | 
					        self.browserLog = open(BROWSERLOG_FILE, "w")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def teardown(self):
 | 
				
			||||||
 | 
					        self.process.terminate()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # If the browser is still running, wait up to ten seconds for it to quit
 | 
				
			||||||
 | 
					        if self.process and self.process.poll() is None:
 | 
				
			||||||
 | 
					            checks = 0
 | 
				
			||||||
 | 
					            while self.process.poll() is None and checks < 20:
 | 
				
			||||||
 | 
					                checks += 1
 | 
				
			||||||
 | 
					                time.sleep(.5)
 | 
				
			||||||
 | 
					            # If it's still not dead, try to kill it
 | 
				
			||||||
 | 
					            if self.process.poll() is None:
 | 
				
			||||||
 | 
					                print "Process %s is still running. Killing." % self.name
 | 
				
			||||||
 | 
					                self.process.kill()
 | 
				
			||||||
 | 
					                self.process.wait()
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        if self.tempDir is not None and os.path.exists(self.tempDir):
 | 
				
			||||||
 | 
					            shutil.rmtree(self.tempDir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.browserLog.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def start(self, url):
 | 
				
			||||||
 | 
					        raise Exception("Can't start BaseBrowserCommand")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class FirefoxBrowserCommand(BaseBrowserCommand):
 | 
				
			||||||
 | 
					    def _fixupMacPath(self):
 | 
				
			||||||
 | 
					        self.path = os.path.join(self.path, "Contents", "MacOS", "firefox-bin")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def setup(self):
 | 
				
			||||||
 | 
					        super(FirefoxBrowserCommand, self).setup()
 | 
				
			||||||
 | 
					        shutil.copytree(os.path.join(DOC_ROOT, "test", "resources", "firefox"),
 | 
				
			||||||
 | 
					                        self.profileDir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def start(self, url):
 | 
				
			||||||
 | 
					        cmds = [self.path]
 | 
				
			||||||
 | 
					        if platform.system() == "Darwin":
 | 
				
			||||||
 | 
					            cmds.append("-foreground")
 | 
				
			||||||
 | 
					        cmds.extend(["-no-remote", "-profile", self.profileDir, url])
 | 
				
			||||||
 | 
					        self.process = subprocess.Popen(cmds, stdout = self.browserLog, stderr = self.browserLog)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ChromeBrowserCommand(BaseBrowserCommand):
 | 
				
			||||||
 | 
					    def _fixupMacPath(self):
 | 
				
			||||||
 | 
					        self.path = os.path.join(self.path, "Contents", "MacOS", "Google Chrome")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def start(self, url):
 | 
				
			||||||
 | 
					        cmds = [self.path]
 | 
				
			||||||
 | 
					        cmds.extend(["--user-data-dir=%s" % self.profileDir,
 | 
				
			||||||
 | 
					                     "--no-first-run", "--disable-sync", url])
 | 
				
			||||||
 | 
					        self.process = subprocess.Popen(cmds, stdout = self.browserLog, stderr = self.browserLog)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def makeBrowserCommand(browser):
 | 
				
			||||||
 | 
					    path = browser["path"].lower()
 | 
				
			||||||
 | 
					    name = browser["name"]
 | 
				
			||||||
 | 
					    if name is not None:
 | 
				
			||||||
 | 
					        name = name.lower()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    types = {"firefox": FirefoxBrowserCommand,
 | 
				
			||||||
 | 
					             "chrome": ChromeBrowserCommand }
 | 
				
			||||||
 | 
					    command = None
 | 
				
			||||||
 | 
					    for key in types.keys():
 | 
				
			||||||
 | 
					        if (name and name.find(key) > -1) or path.find(key) > -1:
 | 
				
			||||||
 | 
					            command = types[key](browser)
 | 
				
			||||||
 | 
					            command.name = command.name or key
 | 
				
			||||||
 | 
					            break
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if command is None:
 | 
				
			||||||
 | 
					        raise Exception("Unrecognized browser: %s" % browser)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return command 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def makeBrowserCommands(browserManifestFile):
 | 
				
			||||||
 | 
					    with open(browserManifestFile) as bmf:
 | 
				
			||||||
 | 
					        browsers = [makeBrowserCommand(browser) for browser in json.load(bmf)]
 | 
				
			||||||
 | 
					    return browsers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def downloadLinkedPDF(f):
 | 
				
			||||||
 | 
					    linkFile = open(f +'.link')
 | 
				
			||||||
 | 
					    link = linkFile.read()
 | 
				
			||||||
 | 
					    linkFile.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sys.stdout.write('Downloading '+ link +' to '+ f +' ...')
 | 
				
			||||||
 | 
					    sys.stdout.flush()
 | 
				
			||||||
 | 
					    response = urllib2.urlopen(link)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with open(f, 'wb') as out:
 | 
				
			||||||
 | 
					        out.write(response.read())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    print 'done'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def downloadLinkedPDFs(manifestList):
 | 
				
			||||||
 | 
					    for item in manifestList:
 | 
				
			||||||
 | 
					        f, isLink = item['file'], item.get('link', False)
 | 
				
			||||||
 | 
					        if isLink and not os.access(f, os.R_OK):
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
 | 
					                downloadLinkedPDF(f)
 | 
				
			||||||
 | 
					            except:
 | 
				
			||||||
 | 
					                exc_type, exc_value, exc_traceback = sys.exc_info()
 | 
				
			||||||
 | 
					                print 'ERROR: Unable to download file "' + f + '".'
 | 
				
			||||||
 | 
					                open(f, 'wb').close()
 | 
				
			||||||
 | 
					                with open(f + '.error', 'w') as out:
 | 
				
			||||||
 | 
					                  out.write('\n'.join(traceback.format_exception(exc_type,
 | 
				
			||||||
 | 
					                                                                 exc_value,
 | 
				
			||||||
 | 
					                                                                 exc_traceback)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def verifyPDFs(manifestList):
 | 
				
			||||||
 | 
					    error = False
 | 
				
			||||||
 | 
					    for item in manifestList:
 | 
				
			||||||
 | 
					        f = item['file']
 | 
				
			||||||
 | 
					        if os.path.isfile(f + '.error'):
 | 
				
			||||||
 | 
					            print 'WARNING: File was not downloaded. See "' + f + '.error" file.'
 | 
				
			||||||
 | 
					            error = True
 | 
				
			||||||
 | 
					        elif os.access(f, os.R_OK):
 | 
				
			||||||
 | 
					            fileMd5 = hashlib.md5(open(f, 'rb').read()).hexdigest()
 | 
				
			||||||
 | 
					            if 'md5' not in item:
 | 
				
			||||||
 | 
					                print 'WARNING: Missing md5 for file "' + f + '".',
 | 
				
			||||||
 | 
					                print 'Hash for current file is "' + fileMd5 + '"'
 | 
				
			||||||
 | 
					                error = True
 | 
				
			||||||
 | 
					                continue
 | 
				
			||||||
 | 
					            md5 = item['md5']
 | 
				
			||||||
 | 
					            if fileMd5 != md5:
 | 
				
			||||||
 | 
					                print 'WARNING: MD5 of file "' + f + '" does not match file.',
 | 
				
			||||||
 | 
					                print 'Expected "' + md5 + '" computed "' + fileMd5 + '"'
 | 
				
			||||||
 | 
					                error = True
 | 
				
			||||||
 | 
					                continue
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            print 'WARNING: Unable to open file for reading "' + f + '".'
 | 
				
			||||||
 | 
					            error = True
 | 
				
			||||||
 | 
					    return not error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def getTestBrowsers(options):
 | 
				
			||||||
 | 
					    testBrowsers = []
 | 
				
			||||||
 | 
					    if options.browserManifestFile:
 | 
				
			||||||
 | 
					        testBrowsers = makeBrowserCommands(options.browserManifestFile)
 | 
				
			||||||
 | 
					    elif options.browser:
 | 
				
			||||||
 | 
					        testBrowsers = [makeBrowserCommand({"path":options.browser, "name":None})]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if options.browserManifestFile or options.browser:
 | 
				
			||||||
 | 
					        assert len(testBrowsers) > 0
 | 
				
			||||||
 | 
					    return testBrowsers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def setUp(options):
 | 
				
			||||||
 | 
					    # Only serve files from a pdf.js clone
 | 
				
			||||||
 | 
					    assert not GIT_CLONE_CHECK or os.path.isfile('../src/pdf.js') and os.path.isdir('../.git')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if options.masterMode and os.path.isdir(TMPDIR):
 | 
				
			||||||
 | 
					        print 'Temporary snapshot dir tmp/ is still around.'
 | 
				
			||||||
 | 
					        print 'tmp/ can be removed if it has nothing you need.'
 | 
				
			||||||
 | 
					        if options.noPrompts or prompt('SHOULD THIS SCRIPT REMOVE tmp/?  THINK CAREFULLY'):
 | 
				
			||||||
 | 
					            subprocess.call(( 'rm', '-rf', 'tmp' ))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assert not os.path.isdir(TMPDIR)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    testBrowsers = getTestBrowsers(options)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with open(options.manifestFile) as mf:
 | 
				
			||||||
 | 
					        manifestList = json.load(mf)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if not options.noDownload:
 | 
				
			||||||
 | 
					        downloadLinkedPDFs(manifestList)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if not verifyPDFs(manifestList):
 | 
				
			||||||
 | 
					          print 'Unable to verify the checksum for the files that are used for testing.'
 | 
				
			||||||
 | 
					          print 'Please re-download the files, or adjust the MD5 checksum in the manifest for the files listed above.\n'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for b in testBrowsers:
 | 
				
			||||||
 | 
					        State.taskResults[b.name] = { }
 | 
				
			||||||
 | 
					        State.remaining[b.name] = len(manifestList)
 | 
				
			||||||
 | 
					        State.lastPost[b.name] = int(time.time())
 | 
				
			||||||
 | 
					        for item in manifestList:
 | 
				
			||||||
 | 
					            id, rounds = item['id'], int(item['rounds'])
 | 
				
			||||||
 | 
					            State.manifest[id] = item
 | 
				
			||||||
 | 
					            taskResults = [ ]
 | 
				
			||||||
 | 
					            for r in xrange(rounds):
 | 
				
			||||||
 | 
					                taskResults.append([ ])
 | 
				
			||||||
 | 
					            State.taskResults[b.name][id] = taskResults
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if options.statsFile != None:
 | 
				
			||||||
 | 
					        State.saveStats = True
 | 
				
			||||||
 | 
					    return testBrowsers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def setUpUnitTests(options):
 | 
				
			||||||
 | 
					    # Only serve files from a pdf.js clone
 | 
				
			||||||
 | 
					    assert not GIT_CLONE_CHECK or os.path.isfile('../src/pdf.js') and os.path.isdir('../.git')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    testBrowsers = getTestBrowsers(options)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    UnitTestState.browsersRunning = len(testBrowsers)
 | 
				
			||||||
 | 
					    for b in testBrowsers:
 | 
				
			||||||
 | 
					        UnitTestState.lastPost[b.name] = int(time.time())
 | 
				
			||||||
 | 
					    return testBrowsers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def startBrowsers(browsers, options, path):
 | 
				
			||||||
 | 
					    for b in browsers:
 | 
				
			||||||
 | 
					        b.setup()
 | 
				
			||||||
 | 
					        print 'Launching', b.name
 | 
				
			||||||
 | 
					        host = 'http://%s:%s' % (SERVER_HOST, options.port) 
 | 
				
			||||||
 | 
					        qs = '?browser='+ urllib.quote(b.name) +'&manifestFile='+ urllib.quote(options.manifestFile)
 | 
				
			||||||
 | 
					        qs += '&path=' + b.path
 | 
				
			||||||
 | 
					        qs += '&delay=' + str(options.statsDelay)
 | 
				
			||||||
 | 
					        qs += '&masterMode=' + str(options.masterMode)
 | 
				
			||||||
 | 
					        b.start(host + path + qs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def teardownBrowsers(browsers):
 | 
				
			||||||
 | 
					    for b in browsers:
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            b.teardown()
 | 
				
			||||||
 | 
					        except:
 | 
				
			||||||
 | 
					            print "Error cleaning up after browser at ", b.path
 | 
				
			||||||
 | 
					            print "Temp dir was ", b.tempDir
 | 
				
			||||||
 | 
					            print "Error:", sys.exc_info()[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def check(task, results, browser, masterMode):
 | 
				
			||||||
 | 
					    failed = False
 | 
				
			||||||
 | 
					    for r in xrange(len(results)):
 | 
				
			||||||
 | 
					        pageResults = results[r]
 | 
				
			||||||
 | 
					        for p in xrange(len(pageResults)):
 | 
				
			||||||
 | 
					            pageResult = pageResults[p]
 | 
				
			||||||
 | 
					            if pageResult is None:
 | 
				
			||||||
 | 
					                continue
 | 
				
			||||||
 | 
					            failure = pageResult.failure
 | 
				
			||||||
 | 
					            if failure:
 | 
				
			||||||
 | 
					                failed = True
 | 
				
			||||||
 | 
					                if os.path.isfile(task['file'] + '.error'):
 | 
				
			||||||
 | 
					                  print 'TEST-SKIPPED | PDF was not downloaded', task['id'], '| in', browser, '| page', p + 1, 'round', r, '|', failure
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                  State.numErrors += 1
 | 
				
			||||||
 | 
					                  print 'TEST-UNEXPECTED-FAIL | test failed', task['id'], '| in', browser, '| page', p + 1, 'round', r, '|', failure
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if failed:
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    kind = task['type']
 | 
				
			||||||
 | 
					    if 'eq' == kind or 'text' == kind:
 | 
				
			||||||
 | 
					        checkEq(task, results, browser, masterMode)
 | 
				
			||||||
 | 
					    elif 'fbf' == kind:
 | 
				
			||||||
 | 
					        checkFBF(task, results, browser)
 | 
				
			||||||
 | 
					    elif 'load' == kind:
 | 
				
			||||||
 | 
					        checkLoad(task, results, browser)
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        assert 0 and 'Unknown test type'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def createDir(dir):
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        os.makedirs(dir)
 | 
				
			||||||
 | 
					    except OSError, e:
 | 
				
			||||||
 | 
					        if e.errno != 17: # file exists
 | 
				
			||||||
 | 
					            print >>sys.stderr, 'Creating', dir, 'failed!'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def readDataUri(data):
 | 
				
			||||||
 | 
					    metadata, encoded = data.rsplit(",", 1)
 | 
				
			||||||
 | 
					    return base64.b64decode(encoded)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def checkEq(task, results, browser, masterMode):
 | 
				
			||||||
 | 
					    pfx = os.path.join(REFDIR, sys.platform, browser, task['id'])
 | 
				
			||||||
 | 
					    testSnapshotDir = os.path.join(TEST_SNAPSHOTS, sys.platform, browser, task['id'])
 | 
				
			||||||
 | 
					    results = results[0]
 | 
				
			||||||
 | 
					    taskId = task['id']
 | 
				
			||||||
 | 
					    taskType = task['type']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    passed = True
 | 
				
			||||||
 | 
					    for result in results:
 | 
				
			||||||
 | 
					        page = result.page
 | 
				
			||||||
 | 
					        snapshot = readDataUri(result.snapshot)
 | 
				
			||||||
 | 
					        ref = None
 | 
				
			||||||
 | 
					        eq = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        path = os.path.join(pfx, str(page) + '.png')
 | 
				
			||||||
 | 
					        if not os.access(path, os.R_OK):
 | 
				
			||||||
 | 
					            State.numEqNoSnapshot += 1
 | 
				
			||||||
 | 
					            if not masterMode:
 | 
				
			||||||
 | 
					                print 'WARNING: no reference snapshot', path
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            f = open(path, 'rb')
 | 
				
			||||||
 | 
					            ref = f.read()
 | 
				
			||||||
 | 
					            f.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            eq = (ref == snapshot)
 | 
				
			||||||
 | 
					            if not eq:
 | 
				
			||||||
 | 
					                print 'TEST-UNEXPECTED-FAIL |', taskType, taskId, '| in', browser, '| rendering of page', page, '!= reference rendering'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if not State.eqLog:
 | 
				
			||||||
 | 
					                    State.eqLog = open(EQLOG_FILE, 'w')
 | 
				
			||||||
 | 
					                eqLog = State.eqLog
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                createDir(testSnapshotDir)
 | 
				
			||||||
 | 
					                testSnapshotPath = os.path.join(testSnapshotDir, str(page) + '.png')
 | 
				
			||||||
 | 
					                handle = open(testSnapshotPath, 'wb')
 | 
				
			||||||
 | 
					                handle.write(snapshot)
 | 
				
			||||||
 | 
					                handle.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                refSnapshotPath = os.path.join(testSnapshotDir, str(page) + '_ref.png')
 | 
				
			||||||
 | 
					                handle = open(refSnapshotPath, 'wb')
 | 
				
			||||||
 | 
					                handle.write(ref)
 | 
				
			||||||
 | 
					                handle.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                # NB: this follows the format of Mozilla reftest
 | 
				
			||||||
 | 
					                # output so that we can reuse its reftest-analyzer
 | 
				
			||||||
 | 
					                # script
 | 
				
			||||||
 | 
					                eqLog.write('REFTEST TEST-UNEXPECTED-FAIL | ' + browser +'-'+ taskId +'-page'+ str(page) + ' | image comparison (==)\n')
 | 
				
			||||||
 | 
					                eqLog.write('REFTEST   IMAGE 1 (TEST): ' + testSnapshotPath + '\n')
 | 
				
			||||||
 | 
					                eqLog.write('REFTEST   IMAGE 2 (REFERENCE): ' + refSnapshotPath + '\n')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                passed = False
 | 
				
			||||||
 | 
					                State.numEqFailures += 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if masterMode and (ref is None or not eq):
 | 
				
			||||||
 | 
					            tmpTaskDir = os.path.join(TMPDIR, sys.platform, browser, task['id'])
 | 
				
			||||||
 | 
					            createDir(tmpTaskDir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            handle = open(os.path.join(tmpTaskDir, str(page)) + '.png', 'wb')
 | 
				
			||||||
 | 
					            handle.write(snapshot)
 | 
				
			||||||
 | 
					            handle.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if passed:
 | 
				
			||||||
 | 
					        print 'TEST-PASS |', taskType, 'test', task['id'], '| in', browser
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def checkFBF(task, results, browser):
 | 
				
			||||||
 | 
					    round0, round1 = results[0], results[1]
 | 
				
			||||||
 | 
					    assert len(round0) == len(round1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    passed = True
 | 
				
			||||||
 | 
					    for page in xrange(len(round1)):
 | 
				
			||||||
 | 
					        r0Page, r1Page = round0[page], round1[page]
 | 
				
			||||||
 | 
					        if r0Page is None:
 | 
				
			||||||
 | 
					            break
 | 
				
			||||||
 | 
					        if r0Page.snapshot != r1Page.snapshot:
 | 
				
			||||||
 | 
					            print 'TEST-UNEXPECTED-FAIL | forward-back-forward test', task['id'], '| in', browser, '| first rendering of page', page + 1, '!= second'
 | 
				
			||||||
 | 
					            passed = False
 | 
				
			||||||
 | 
					            State.numFBFFailures += 1
 | 
				
			||||||
 | 
					    if passed:
 | 
				
			||||||
 | 
					        print 'TEST-PASS | forward-back-forward test', task['id'], '| in', browser
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def checkLoad(task, results, browser):
 | 
				
			||||||
 | 
					    # Load just checks for absence of failure, so if we got here the
 | 
				
			||||||
 | 
					    # test has passed
 | 
				
			||||||
 | 
					    print 'TEST-PASS | load test', task['id'], '| in', browser
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def processResults(options):
 | 
				
			||||||
 | 
					    print ''
 | 
				
			||||||
 | 
					    numFatalFailures = (State.numErrors + State.numFBFFailures)
 | 
				
			||||||
 | 
					    if 0 == State.numEqFailures and 0 == numFatalFailures:
 | 
				
			||||||
 | 
					        print 'All regression tests passed.'
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        print 'OHNOES!  Some tests failed!'
 | 
				
			||||||
 | 
					        if 0 < State.numErrors:
 | 
				
			||||||
 | 
					            print '  errors:', State.numErrors
 | 
				
			||||||
 | 
					        if 0 < State.numEqFailures:
 | 
				
			||||||
 | 
					            print '  different ref/snapshot:', State.numEqFailures
 | 
				
			||||||
 | 
					        if 0 < State.numFBFFailures:
 | 
				
			||||||
 | 
					            print '  different first/second rendering:', State.numFBFFailures
 | 
				
			||||||
 | 
					    if options.statsFile != None:
 | 
				
			||||||
 | 
					        with open(options.statsFile, 'w') as sf:
 | 
				
			||||||
 | 
					            sf.write(json.dumps(State.stats, sort_keys=True, indent=4))
 | 
				
			||||||
 | 
					        print 'Wrote stats file: ' + options.statsFile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def maybeUpdateRefImages(options, browser):
 | 
				
			||||||
 | 
					    if options.masterMode and (0 < State.numEqFailures or 0 < State.numEqNoSnapshot): 
 | 
				
			||||||
 | 
					        print "Some eq tests failed or didn't have snapshots."
 | 
				
			||||||
 | 
					        print 'Checking to see if master references can be updated...'
 | 
				
			||||||
 | 
					        numFatalFailures = (State.numErrors + State.numFBFFailures)
 | 
				
			||||||
 | 
					        if 0 < numFatalFailures:
 | 
				
			||||||
 | 
					            print '  No.  Some non-eq tests failed.'
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            print '  Yes!  The references in tmp/ can be synced with ref/.'
 | 
				
			||||||
 | 
					            if options.reftest:                                                                                                              
 | 
				
			||||||
 | 
					                startReftest(browser, options)
 | 
				
			||||||
 | 
					            if options.noPrompts or prompt('Would you like to update the master copy in ref/?'):
 | 
				
			||||||
 | 
					                sys.stdout.write('  Updating ref/ ... ')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if not os.path.exists('ref'):
 | 
				
			||||||
 | 
					                    subprocess.check_call('mkdir ref', shell = True)
 | 
				
			||||||
 | 
					                subprocess.check_call('cp -Rf tmp/* ref/', shell = True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                print 'done'
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                print '  OK, not updating.'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def startReftest(browser, options):
 | 
				
			||||||
 | 
					    url = "http://%s:%s" % (SERVER_HOST, options.port)
 | 
				
			||||||
 | 
					    url += "/test/resources/reftest-analyzer.xhtml"
 | 
				
			||||||
 | 
					    url += "#web=/test/eq.log"
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        browser.setup()
 | 
				
			||||||
 | 
					        browser.start(url)
 | 
				
			||||||
 | 
					        print "Waiting for browser..."
 | 
				
			||||||
 | 
					        browser.process.wait()
 | 
				
			||||||
 | 
					    finally:
 | 
				
			||||||
 | 
					        teardownBrowsers([browser])
 | 
				
			||||||
 | 
					    print "Completed reftest usage."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def runTests(options, browsers):
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        shutil.rmtree(TEST_SNAPSHOTS);
 | 
				
			||||||
 | 
					    except OSError, e:
 | 
				
			||||||
 | 
					        if e.errno != 2: # folder doesn't exist
 | 
				
			||||||
 | 
					            print >>sys.stderr, 'Deleting', dir, 'failed!'
 | 
				
			||||||
 | 
					    t1 = time.time()
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        startBrowsers(browsers, options, '/test/test_slave.html')
 | 
				
			||||||
 | 
					        while not State.done:
 | 
				
			||||||
 | 
					            for b in State.lastPost:
 | 
				
			||||||
 | 
					                if State.remaining[b] > 0 and int(time.time()) - State.lastPost[b] > BROWSER_TIMEOUT:
 | 
				
			||||||
 | 
					                    print 'TEST-UNEXPECTED-FAIL | test failed', b, "has not responded in", BROWSER_TIMEOUT, "s"
 | 
				
			||||||
 | 
					                    State.numErrors += State.remaining[b]
 | 
				
			||||||
 | 
					                    State.remaining[b] = 0
 | 
				
			||||||
 | 
					                    checkIfDone()
 | 
				
			||||||
 | 
					            time.sleep(1)
 | 
				
			||||||
 | 
					        processResults(options)
 | 
				
			||||||
 | 
					    finally:
 | 
				
			||||||
 | 
					        teardownBrowsers(browsers)
 | 
				
			||||||
 | 
					    t2 = time.time()
 | 
				
			||||||
 | 
					    print "Runtime was", int(t2 - t1), "seconds"
 | 
				
			||||||
 | 
					    if State.eqLog:
 | 
				
			||||||
 | 
					        State.eqLog.close();
 | 
				
			||||||
 | 
					    if options.masterMode:
 | 
				
			||||||
 | 
					        maybeUpdateRefImages(options, browsers[0])
 | 
				
			||||||
 | 
					    elif options.reftest and State.numEqFailures > 0:
 | 
				
			||||||
 | 
					        print "\nStarting reftest harness to examine %d eq test failures." % State.numEqFailures
 | 
				
			||||||
 | 
					        startReftest(browsers[0], options)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def runUnitTests(options, browsers, url, name):
 | 
				
			||||||
 | 
					    t1 = time.time()
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        startBrowsers(browsers, options, url)
 | 
				
			||||||
 | 
					        while UnitTestState.browsersRunning > 0:
 | 
				
			||||||
 | 
					            for b in UnitTestState.lastPost:
 | 
				
			||||||
 | 
					                if UnitTestState.lastPost[b] != None and int(time.time()) - UnitTestState.lastPost[b] > BROWSER_TIMEOUT:
 | 
				
			||||||
 | 
					                    print 'TEST-UNEXPECTED-FAIL | test failed', b, "has not responded in", BROWSER_TIMEOUT, "s"
 | 
				
			||||||
 | 
					                    UnitTestState.lastPost[b] = None
 | 
				
			||||||
 | 
					                    UnitTestState.browsersRunning -= 1
 | 
				
			||||||
 | 
					                    UnitTestState.numErrors += 1
 | 
				
			||||||
 | 
					            time.sleep(1)
 | 
				
			||||||
 | 
					        print ''
 | 
				
			||||||
 | 
					        print 'Ran', UnitTestState.numRun, 'tests'
 | 
				
			||||||
 | 
					        if UnitTestState.numErrors > 0:
 | 
				
			||||||
 | 
					            print 'OHNOES!  Some', name, 'tests failed!'
 | 
				
			||||||
 | 
					            print '  ', UnitTestState.numErrors, 'of', UnitTestState.numRun, 'failed'
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            print 'All', name, 'tests passed.'
 | 
				
			||||||
 | 
					    finally:
 | 
				
			||||||
 | 
					        teardownBrowsers(browsers)
 | 
				
			||||||
 | 
					    t2 = time.time()
 | 
				
			||||||
 | 
					    print '', name, 'tests runtime was', int(t2 - t1), 'seconds'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def main():
 | 
				
			||||||
 | 
					    optionParser = TestOptions()
 | 
				
			||||||
 | 
					    options, args = optionParser.parse_args()
 | 
				
			||||||
 | 
					    options = optionParser.verifyOptions(options)
 | 
				
			||||||
 | 
					    if options == None:
 | 
				
			||||||
 | 
					        sys.exit(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if options.unitTest or options.fontTest:
 | 
				
			||||||
 | 
					        httpd = TestServer((SERVER_HOST, options.port), UnitTestHandler)
 | 
				
			||||||
 | 
					        httpd_thread = threading.Thread(target=httpd.serve_forever)
 | 
				
			||||||
 | 
					        httpd_thread.setDaemon(True)
 | 
				
			||||||
 | 
					        httpd_thread.start()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        browsers = setUpUnitTests(options)
 | 
				
			||||||
 | 
					        if len(browsers) > 0:
 | 
				
			||||||
 | 
					            if options.unitTest:
 | 
				
			||||||
 | 
					              runUnitTests(options, browsers, '/test/unit/unit_test.html', 'unit')
 | 
				
			||||||
 | 
					            if options.fontTest:
 | 
				
			||||||
 | 
					              runUnitTests(options, browsers, '/test/font/font_test.html', 'font')
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        httpd = TestServer((SERVER_HOST, options.port), PDFTestHandler)
 | 
				
			||||||
 | 
					        httpd.masterMode = options.masterMode
 | 
				
			||||||
 | 
					        httpd_thread = threading.Thread(target=httpd.serve_forever)
 | 
				
			||||||
 | 
					        httpd_thread.setDaemon(True)
 | 
				
			||||||
 | 
					        httpd_thread.start()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        browsers = setUp(options)
 | 
				
			||||||
 | 
					        if len(browsers) > 0:
 | 
				
			||||||
 | 
					            runTests(options, browsers)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            # just run the server
 | 
				
			||||||
 | 
					            print "Running HTTP server. Press Ctrl-C to quit."
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
 | 
					                while True:
 | 
				
			||||||
 | 
					                    time.sleep(1)
 | 
				
			||||||
 | 
					            except (KeyboardInterrupt):
 | 
				
			||||||
 | 
					                print "\nExiting."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == '__main__':
 | 
				
			||||||
 | 
					    main()
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								public/vendor/pdfjs/web/images/Thumbs.db
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								public/vendor/pdfjs/web/images/Thumbs.db
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										33
									
								
								public/vendor/sizzle/.bower.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								public/vendor/sizzle/.bower.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "name": "sizzle",
 | 
				
			||||||
 | 
					  "version": "1.10.16",
 | 
				
			||||||
 | 
					  "main": "./dist/sizzle.js",
 | 
				
			||||||
 | 
					  "devDependencies": {
 | 
				
			||||||
 | 
					    "qunit": "~1.12.0",
 | 
				
			||||||
 | 
					    "benchmark": "~1.0.0",
 | 
				
			||||||
 | 
					    "requirejs": "~2.1.8",
 | 
				
			||||||
 | 
					    "requirejs-domready": "~2.0.1",
 | 
				
			||||||
 | 
					    "requirejs-text": "~2.0.10"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "ignore": [
 | 
				
			||||||
 | 
					    "**/.*",
 | 
				
			||||||
 | 
					    "package.json",
 | 
				
			||||||
 | 
					    "bower.json",
 | 
				
			||||||
 | 
					    "speed",
 | 
				
			||||||
 | 
					    "Makefile",
 | 
				
			||||||
 | 
					    "*.md",
 | 
				
			||||||
 | 
					    "*.txt",
 | 
				
			||||||
 | 
					    "src",
 | 
				
			||||||
 | 
					    "Gruntfile.js"
 | 
				
			||||||
 | 
					  ],
 | 
				
			||||||
 | 
					  "homepage": "https://github.com/jquery/sizzle",
 | 
				
			||||||
 | 
					  "_release": "1.10.16",
 | 
				
			||||||
 | 
					  "_resolution": {
 | 
				
			||||||
 | 
					    "type": "version",
 | 
				
			||||||
 | 
					    "tag": "1.10.16",
 | 
				
			||||||
 | 
					    "commit": "0fd151739d05648118002914c7a638411bbd0dbe"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "_source": "git://github.com/jquery/sizzle.git",
 | 
				
			||||||
 | 
					  "_target": "1.10.16",
 | 
				
			||||||
 | 
					  "_originalSource": "sizzle"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										2015
									
								
								public/vendor/sizzle/dist/sizzle.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2015
									
								
								public/vendor/sizzle/dist/sizzle.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										3
									
								
								public/vendor/sizzle/dist/sizzle.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								public/vendor/sizzle/dist/sizzle.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1
									
								
								public/vendor/sizzle/dist/sizzle.min.map
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								public/vendor/sizzle/dist/sizzle.min.map
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										10
									
								
								public/vendor/sizzle/tasks/commit.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								public/vendor/sizzle/tasks/commit.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					"use strict";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var exec = require( "child_process" ).exec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = function( grunt ) {
 | 
				
			||||||
 | 
						grunt.registerTask( "commit", "Add and commit changes", function( message ) {
 | 
				
			||||||
 | 
							// Always add dist directory
 | 
				
			||||||
 | 
							exec( "git add dist && git commit -m " + message, this.async() );
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										34
									
								
								public/vendor/sizzle/tasks/compile.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								public/vendor/sizzle/tasks/compile.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					"use strict";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = function( grunt ) {
 | 
				
			||||||
 | 
						grunt.registerMultiTask(
 | 
				
			||||||
 | 
							"compile",
 | 
				
			||||||
 | 
							"Compile sizzle.js to the dist directory. Embed date/version.",
 | 
				
			||||||
 | 
							function() {
 | 
				
			||||||
 | 
								var data = this.data,
 | 
				
			||||||
 | 
									dest = data.dest,
 | 
				
			||||||
 | 
									src = data.src,
 | 
				
			||||||
 | 
									version = grunt.config( "pkg.version" ),
 | 
				
			||||||
 | 
									compiled = grunt.file.read( src );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Embed version and date
 | 
				
			||||||
 | 
								compiled = compiled
 | 
				
			||||||
 | 
									.replace( /@VERSION/g, version )
 | 
				
			||||||
 | 
									.replace( "@DATE", function() {
 | 
				
			||||||
 | 
										var date = new Date();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										// YYYY-MM-DD
 | 
				
			||||||
 | 
										return [
 | 
				
			||||||
 | 
											date.getFullYear(),
 | 
				
			||||||
 | 
											( "0" + ( date.getMonth() + 1 ) ).slice( -2 ),
 | 
				
			||||||
 | 
											( "0" + date.getDate() ).slice( -2 )
 | 
				
			||||||
 | 
										].join( "-" );
 | 
				
			||||||
 | 
									});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Write source to file
 | 
				
			||||||
 | 
								grunt.file.write( dest, compiled );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								grunt.log.ok( "File written to " + dest );
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										35
									
								
								public/vendor/sizzle/tasks/dist.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								public/vendor/sizzle/tasks/dist.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					"use strict";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var fs = require( "fs" );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = function( grunt ) {
 | 
				
			||||||
 | 
						grunt.registerTask( "dist", "Process files for distribution", function() {
 | 
				
			||||||
 | 
							var files = grunt.file.expand( { filter: "isFile" }, "dist/*" );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							files.forEach(function( filename ) {
 | 
				
			||||||
 | 
								var map,
 | 
				
			||||||
 | 
									text = fs.readFileSync( filename, "utf8" );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Modify map/min so that it points to files in the same folder;
 | 
				
			||||||
 | 
								// see https://github.com/mishoo/UglifyJS2/issues/47
 | 
				
			||||||
 | 
								if ( /\.map$/.test( filename ) ) {
 | 
				
			||||||
 | 
									text = text.replace( /"dist\//g, "\"" );
 | 
				
			||||||
 | 
									fs.writeFileSync( filename, text, "utf-8" );
 | 
				
			||||||
 | 
								} else if ( /\.min\.js$/.test( filename ) ) {
 | 
				
			||||||
 | 
									// Wrap sourceMap directive in multiline comments (#13274)
 | 
				
			||||||
 | 
									text = text.replace( /\n?(\/\/@\s*sourceMappingURL=)(.*)/,
 | 
				
			||||||
 | 
										function( _, directive, path ) {
 | 
				
			||||||
 | 
											map = "\n" + directive + path.replace( /^dist\//, "" );
 | 
				
			||||||
 | 
											return "";
 | 
				
			||||||
 | 
										});
 | 
				
			||||||
 | 
									if ( map ) {
 | 
				
			||||||
 | 
										text = text.replace( /(^\/\*[\w\W]*?)\s*\*\/|$/,
 | 
				
			||||||
 | 
											function( _, comment ) {
 | 
				
			||||||
 | 
												return ( comment || "\n/*" ) + map + "\n*/";
 | 
				
			||||||
 | 
											});
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									fs.writeFileSync( filename, text, "utf-8" );
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										43
									
								
								public/vendor/sizzle/tasks/release.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								public/vendor/sizzle/tasks/release.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,43 @@
 | 
				
			|||||||
 | 
					"use strict";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var exec = require( "child_process" ).exec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = function( grunt ) {
 | 
				
			||||||
 | 
						var rpreversion = /(\d\.\d+\.\d+)-pre/;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						grunt.registerTask( "release",
 | 
				
			||||||
 | 
							"Release a version of sizzle, updates a pre version to released, " +
 | 
				
			||||||
 | 
							"inserts `next` as the new pre version", function( next ) {
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							if ( !rpreversion.test( next ) ) {
 | 
				
			||||||
 | 
								grunt.fatal( "Next version should be a -pre version (x.x.x-pre): " + next );
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							var done,
 | 
				
			||||||
 | 
								version = grunt.config( "pkg.version" );
 | 
				
			||||||
 | 
							if ( !rpreversion.test( version ) ) {
 | 
				
			||||||
 | 
								grunt.fatal( "Existing version is not a pre version: " + version );
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							version = version.replace( rpreversion, "$1" );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							done = this.async();
 | 
				
			||||||
 | 
							exec( "git diff --quiet HEAD", function( err ) {
 | 
				
			||||||
 | 
								if ( err ) {
 | 
				
			||||||
 | 
									grunt.fatal( "The working directory should be clean when releasing. Commit or stash changes." );
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								// Build to dist directories along with a map and tag the release
 | 
				
			||||||
 | 
								grunt.task.run([
 | 
				
			||||||
 | 
									// Commit new version
 | 
				
			||||||
 | 
									"version:" + version,
 | 
				
			||||||
 | 
									// Tag new version
 | 
				
			||||||
 | 
									"tag:" + version,
 | 
				
			||||||
 | 
									// Commit next version
 | 
				
			||||||
 | 
									"version:" + next
 | 
				
			||||||
 | 
								]);
 | 
				
			||||||
 | 
								done();
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										9
									
								
								public/vendor/sizzle/tasks/tag.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								public/vendor/sizzle/tasks/tag.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					"use strict";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var exec = require( "child_process" ).exec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = function( grunt ) {
 | 
				
			||||||
 | 
						grunt.registerTask( "tag", "Tag the specified version", function( version ) {
 | 
				
			||||||
 | 
							exec( "git tag " + version, this.async() );
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										35
									
								
								public/vendor/sizzle/tasks/version.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								public/vendor/sizzle/tasks/version.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					"use strict";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var exec = require( "child_process" ).exec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = function( grunt ) {
 | 
				
			||||||
 | 
						grunt.registerTask( "version", "Commit a new version", function( version ) {
 | 
				
			||||||
 | 
							if ( !/\d\.\d+\.\d+(?:-pre)?/.test( version ) ) {
 | 
				
			||||||
 | 
								grunt.fatal( "Version must follow semver release format: " + version );
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							var done = this.async(),
 | 
				
			||||||
 | 
								files = grunt.config( "version.files" ),
 | 
				
			||||||
 | 
								rversion = /("version":\s*")[^"]+/;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Update version in specified files
 | 
				
			||||||
 | 
							files.forEach(function( filename ) {
 | 
				
			||||||
 | 
								var text = grunt.file.read( filename );
 | 
				
			||||||
 | 
								text = text.replace( rversion, "$1" + version );
 | 
				
			||||||
 | 
								grunt.file.write( filename, text );
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Add files to git index
 | 
				
			||||||
 | 
							exec( "git add -A", function( err ) {
 | 
				
			||||||
 | 
								if ( err ) {
 | 
				
			||||||
 | 
									grunt.fatal( err );
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								// Commit next pre version
 | 
				
			||||||
 | 
								grunt.config( "pkg.version", version );
 | 
				
			||||||
 | 
								grunt.task.run([ "build", "uglify", "dist", "commit:'Update version to " + version + "'" ]);
 | 
				
			||||||
 | 
								done();
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										0
									
								
								public/vendor/sizzle/test/data/empty.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								public/vendor/sizzle/test/data/empty.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
								
								
									
										22
									
								
								public/vendor/sizzle/test/data/mixed_sort.html
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								public/vendor/sizzle/test/data/mixed_sort.html
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					<!DOCTYPE html>
 | 
				
			||||||
 | 
					<html lang="en">
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
						<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 | 
				
			||||||
 | 
						<script>var QUnit = parent.QUnit</script>
 | 
				
			||||||
 | 
						<script src="testinit.js"></script>
 | 
				
			||||||
 | 
						<script src="../../dist/sizzle.js"></script>
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
						<script>
 | 
				
			||||||
 | 
							var doc = parent.document,
 | 
				
			||||||
 | 
								unframed = [ doc.getElementById( "qunit-fixture" ), doc.body, doc.documentElement ],
 | 
				
			||||||
 | 
								framed = Sizzle( "*" );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							window.parent.iframeCallback(
 | 
				
			||||||
 | 
								Sizzle.uniqueSort( unframed.concat( framed ) ),
 | 
				
			||||||
 | 
								framed.concat( unframed.reverse() ),
 | 
				
			||||||
 | 
								"Mixed array was sorted correctly"
 | 
				
			||||||
 | 
							);
 | 
				
			||||||
 | 
						</script>
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
							
								
								
									
										136
									
								
								public/vendor/sizzle/test/data/testinit.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								public/vendor/sizzle/test/data/testinit.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,136 @@
 | 
				
			|||||||
 | 
					var fireNative,
 | 
				
			||||||
 | 
						jQuery = this.jQuery || "jQuery", // For testing .noConflict()
 | 
				
			||||||
 | 
						$ = this.$ || "$",
 | 
				
			||||||
 | 
						originaljQuery = jQuery,
 | 
				
			||||||
 | 
						original$ = $;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(function() {
 | 
				
			||||||
 | 
						// Config parameter to force basic code paths
 | 
				
			||||||
 | 
						QUnit.config.urlConfig.push({
 | 
				
			||||||
 | 
							id: "basic",
 | 
				
			||||||
 | 
							label: "Bypass optimizations",
 | 
				
			||||||
 | 
							tooltip: "Force use of the most basic code by disabling native querySelectorAll; contains; compareDocumentPosition"
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
						if ( QUnit.urlParams.basic ) {
 | 
				
			||||||
 | 
							document.querySelectorAll = null;
 | 
				
			||||||
 | 
							document.documentElement.contains = null;
 | 
				
			||||||
 | 
							document.documentElement.compareDocumentPosition = null;
 | 
				
			||||||
 | 
							// Return array of length two to pass assertion
 | 
				
			||||||
 | 
							// But support should be false as its not native
 | 
				
			||||||
 | 
							document.getElementsByClassName = function() { return [ 0, 1 ]; };
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					})();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Returns an array of elements with the given IDs
 | 
				
			||||||
 | 
					 * @example q("main", "foo", "bar")
 | 
				
			||||||
 | 
					 * @result [<div id="main">, <span id="foo">, <input id="bar">]
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					function q() {
 | 
				
			||||||
 | 
						var r = [],
 | 
				
			||||||
 | 
							i = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for ( ; i < arguments.length; i++ ) {
 | 
				
			||||||
 | 
							r.push( document.getElementById( arguments[i] ) );
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Asserts that a select matches the given IDs
 | 
				
			||||||
 | 
					 * @param {String} a - Assertion name
 | 
				
			||||||
 | 
					 * @param {String} b - Sizzle selector
 | 
				
			||||||
 | 
					 * @param {String} c - Array of ids to construct what is expected
 | 
				
			||||||
 | 
					 * @example t("Check for something", "//[a]", ["foo", "baar"]);
 | 
				
			||||||
 | 
					 * @result returns true if "//[a]" return two elements with the IDs 'foo' and 'baar'
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					function t( a, b, c ) {
 | 
				
			||||||
 | 
						var f = Sizzle(b),
 | 
				
			||||||
 | 
							s = "",
 | 
				
			||||||
 | 
							i = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for ( ; i < f.length; i++ ) {
 | 
				
			||||||
 | 
							s += ( s && "," ) + '"' + f[ i ].id + '"';
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						deepEqual(f, q.apply( q, c ), a + " (" + b + ")");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Add random number to url to stop caching
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @example url("data/test.html")
 | 
				
			||||||
 | 
					 * @result "data/test.html?10538358428943"
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @example url("data/test.php?foo=bar")
 | 
				
			||||||
 | 
					 * @result "data/test.php?foo=bar&10538358345554"
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					function url( value ) {
 | 
				
			||||||
 | 
						return value + (/\?/.test(value) ? "&" : "?") + new Date().getTime() + "" + parseInt(Math.random()*100000);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var createWithFriesXML = function() {
 | 
				
			||||||
 | 
						var string = '<?xml version="1.0" encoding="UTF-8"?> \
 | 
				
			||||||
 | 
						<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" \
 | 
				
			||||||
 | 
							xmlns:xsd="http://www.w3.org/2001/XMLSchema" \
 | 
				
			||||||
 | 
							xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> \
 | 
				
			||||||
 | 
							<soap:Body> \
 | 
				
			||||||
 | 
								<jsconf xmlns="http://www.example.com/ns1"> \
 | 
				
			||||||
 | 
									<response xmlns:ab="http://www.example.com/ns2"> \
 | 
				
			||||||
 | 
										<meta> \
 | 
				
			||||||
 | 
											<component id="seite1" class="component"> \
 | 
				
			||||||
 | 
												<properties xmlns:cd="http://www.example.com/ns3"> \
 | 
				
			||||||
 | 
													<property name="prop1"> \
 | 
				
			||||||
 | 
														<thing /> \
 | 
				
			||||||
 | 
														<value>1</value> \
 | 
				
			||||||
 | 
													</property> \
 | 
				
			||||||
 | 
													<property name="prop2"> \
 | 
				
			||||||
 | 
														<thing att="something" /> \
 | 
				
			||||||
 | 
													</property> \
 | 
				
			||||||
 | 
													<foo_bar>foo</foo_bar> \
 | 
				
			||||||
 | 
												</properties> \
 | 
				
			||||||
 | 
											</component> \
 | 
				
			||||||
 | 
										</meta> \
 | 
				
			||||||
 | 
									</response> \
 | 
				
			||||||
 | 
								</jsconf> \
 | 
				
			||||||
 | 
							</soap:Body> \
 | 
				
			||||||
 | 
						</soap:Envelope>';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return jQuery.parseXML( string );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fireNative = document.createEvent ?
 | 
				
			||||||
 | 
						function( node, type ) {
 | 
				
			||||||
 | 
							var event = document.createEvent("HTMLEvents");
 | 
				
			||||||
 | 
							event.initEvent( type, true, true );
 | 
				
			||||||
 | 
							node.dispatchEvent( event );
 | 
				
			||||||
 | 
						} :
 | 
				
			||||||
 | 
						function( node, type ) {
 | 
				
			||||||
 | 
							var event = document.createEventObject();
 | 
				
			||||||
 | 
							node.fireEvent( "on" + type, event );
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function testIframeWithCallback( title, fileName, func ) {
 | 
				
			||||||
 | 
						test( title, function() {
 | 
				
			||||||
 | 
							var iframe;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							stop();
 | 
				
			||||||
 | 
							window.iframeCallback = function() {
 | 
				
			||||||
 | 
								var self = this,
 | 
				
			||||||
 | 
									args = arguments;
 | 
				
			||||||
 | 
								setTimeout(function() {
 | 
				
			||||||
 | 
									window.iframeCallback = undefined;
 | 
				
			||||||
 | 
									iframe.remove();
 | 
				
			||||||
 | 
									func.apply( self, args );
 | 
				
			||||||
 | 
									func = function() {};
 | 
				
			||||||
 | 
									start();
 | 
				
			||||||
 | 
								}, 0 );
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
							iframe = jQuery( "<div/>" ).css({ position: "absolute", width: "500px", left: "-600px" })
 | 
				
			||||||
 | 
								.append( jQuery( "<iframe/>" ).attr( "src", url( "./data/" + fileName ) ) )
 | 
				
			||||||
 | 
								.appendTo( "#qunit-fixture" );
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					window.iframeCallback = undefined;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function moduleTeardown() {}
 | 
				
			||||||
							
								
								
									
										242
									
								
								public/vendor/sizzle/test/index.html
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										242
									
								
								public/vendor/sizzle/test/index.html
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,242 @@
 | 
				
			|||||||
 | 
					<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 | 
				
			||||||
 | 
					<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" dir="ltr" id="html">
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
						<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 | 
				
			||||||
 | 
						<title>Sizzle Test Suite</title>
 | 
				
			||||||
 | 
						<link rel="Stylesheet" media="screen" href="libs/qunit/qunit.css" />
 | 
				
			||||||
 | 
						<script type="text/javascript" src="libs/qunit/qunit.js"></script>
 | 
				
			||||||
 | 
						<script type="text/javascript" src="data/testinit.js"></script>
 | 
				
			||||||
 | 
						<script type="text/javascript" src="jquery.js"></script>
 | 
				
			||||||
 | 
						<script type="text/javascript" src="../dist/sizzle.js"></script>
 | 
				
			||||||
 | 
						<script type="text/javascript" src="unit/selector.js"></script>
 | 
				
			||||||
 | 
						<script type="text/javascript" src="unit/utilities.js"></script>
 | 
				
			||||||
 | 
						<script type="text/javascript" src="unit/extending.js"></script>
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<body id="body">
 | 
				
			||||||
 | 
						<div id="qunit"></div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						<!-- Test HTML -->
 | 
				
			||||||
 | 
						<dl id="dl" style="position:absolute;top:-32767px;left:-32767px;width:1px">
 | 
				
			||||||
 | 
						<div id="qunit-fixture">
 | 
				
			||||||
 | 
							<p id="firstp">See <a id="simon1" href="http://simon.incutio.com/archive/2003/03/25/#getElementsBySelector" rel="bookmark">this blog entry</a> for more information.</p>
 | 
				
			||||||
 | 
							<p id="ap">
 | 
				
			||||||
 | 
								Here are some [links] in a normal paragraph: <a id="google" href="http://www.google.com/" title="Google!">Google</a>,
 | 
				
			||||||
 | 
								<a id="groups" href="http://groups.google.com/" class="GROUPS">Google Groups (Link)</a>.
 | 
				
			||||||
 | 
								This link has <code id="code1"><a href="http://smin" id="anchor1">class="blog"</a></code>:
 | 
				
			||||||
 | 
								<a href="http://diveintomark.org/" class="blog" hreflang="en" id="mark">diveintomark</a>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							</p>
 | 
				
			||||||
 | 
							<div id="foo">
 | 
				
			||||||
 | 
								<p id="sndp">Everything inside the red border is inside a div with <code>id="foo"</code>.</p>
 | 
				
			||||||
 | 
								<p lang="en" id="en">This is a normal link: <a id="yahoo" href="http://www.yahoo.com/" class="blogTest">Yahoo</a></p>
 | 
				
			||||||
 | 
								<p id="sap">This link has <code><a href="#2" id="anchor2">class="blog"</a></code>: <a href="http://simon.incutio.com/" class="blog link" id="simon">Simon Willison's Weblog</a></p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
							<div id="nothiddendiv" style="height:1px;background:white;" class="nothiddendiv">
 | 
				
			||||||
 | 
								<div id="nothiddendivchild"></div>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
							<span id="name+value"></span>
 | 
				
			||||||
 | 
							<p id="first">Try them out:</p>
 | 
				
			||||||
 | 
							<ul id="firstUL"></ul>
 | 
				
			||||||
 | 
							<ol id="empty"><!-- comment --></ol>
 | 
				
			||||||
 | 
							<form id="form" action="formaction">
 | 
				
			||||||
 | 
								<label for="action" id="label-for">Action:</label>
 | 
				
			||||||
 | 
								<input type="text" name="action" value="Test" id="text1" maxlength="30"/>
 | 
				
			||||||
 | 
								<input type="text" name="text2" value="Test" id="text2" disabled="disabled"/>
 | 
				
			||||||
 | 
								<input type="radio" name="radio1" id="radio1" value="on"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								<input type="radio" name="radio2" id="radio2" checked="checked"/>
 | 
				
			||||||
 | 
								<input type="checkbox" name="check" id="check1" checked="checked"/>
 | 
				
			||||||
 | 
								<input type="checkbox" id="check2" value="on"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								<input type="hidden" name="hidden" id="hidden1"/>
 | 
				
			||||||
 | 
								<input type="text" style="display:none;" name="foo[bar]" id="hidden2"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								<input type="text" id="name" name="name" value="name" />
 | 
				
			||||||
 | 
								<input type="search" id="search" name="search" value="search" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								<button id="button" name="button" type="button">Button</button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								<textarea id="area1" maxlength="30">foobar</textarea>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								<select name="select1" id="select1">
 | 
				
			||||||
 | 
									<option id="option1a" class="emptyopt" value="">Nothing</option>
 | 
				
			||||||
 | 
									<option id="option1b" value="1">1</option>
 | 
				
			||||||
 | 
									<option id="option1c" value="2">2</option>
 | 
				
			||||||
 | 
									<option id="option1d" value="3">3</option>
 | 
				
			||||||
 | 
								</select>
 | 
				
			||||||
 | 
								<select name="select2" id="select2">
 | 
				
			||||||
 | 
									<option id="option2a" class="emptyopt" value="">Nothing</option>
 | 
				
			||||||
 | 
									<option id="option2b" value="1">1</option>
 | 
				
			||||||
 | 
									<option id="option2c" value="2">2</option>
 | 
				
			||||||
 | 
									<option id="option2d" selected="selected" value="3">3</option>
 | 
				
			||||||
 | 
								</select>
 | 
				
			||||||
 | 
								<select name="select3" id="select3" multiple="multiple">
 | 
				
			||||||
 | 
									<option id="option3a" class="emptyopt" value="">Nothing</option>
 | 
				
			||||||
 | 
									<option id="option3b" selected="selected" value="1">1</option>
 | 
				
			||||||
 | 
									<option id="option3c" selected="selected" value="2">2</option>
 | 
				
			||||||
 | 
									<option id="option3d" value="3">3</option>
 | 
				
			||||||
 | 
									<option id="option3e">no value</option>
 | 
				
			||||||
 | 
								</select>
 | 
				
			||||||
 | 
								<select name="select4" id="select4" multiple="multiple">
 | 
				
			||||||
 | 
									<optgroup disabled="disabled">
 | 
				
			||||||
 | 
										<option id="option4a" class="emptyopt" value="">Nothing</option>
 | 
				
			||||||
 | 
										<option id="option4b" disabled="disabled" selected="selected" value="1">1</option>
 | 
				
			||||||
 | 
										<option id="option4c" selected="selected" value="2">2</option>
 | 
				
			||||||
 | 
									</optgroup>
 | 
				
			||||||
 | 
									<option selected="selected" disabled="disabled" id="option4d" value="3">3</option>
 | 
				
			||||||
 | 
									<option id="option4e">no value</option>
 | 
				
			||||||
 | 
								</select>
 | 
				
			||||||
 | 
								<select name="select5" id="select5">
 | 
				
			||||||
 | 
									<option id="option5a" value="3">1</option>
 | 
				
			||||||
 | 
									<option id="option5b" value="2">2</option>
 | 
				
			||||||
 | 
									<option id="option5c" value="1">3</option>
 | 
				
			||||||
 | 
								</select>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								<object id="object1" codebase="stupid">
 | 
				
			||||||
 | 
									<param name="p1" value="x1" />
 | 
				
			||||||
 | 
									<param name="p2" value="x2" />
 | 
				
			||||||
 | 
								</object>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								<span id="台北Táiběi"></span>
 | 
				
			||||||
 | 
								<span id="台北" lang="中文"></span>
 | 
				
			||||||
 | 
								<span id="utf8class1" class="台北Táiběi 台北"></span>
 | 
				
			||||||
 | 
								<span id="utf8class2" class="台北"></span>
 | 
				
			||||||
 | 
								<span id="foo:bar" class="foo:bar"><span id="foo_descendent"></span></span>
 | 
				
			||||||
 | 
								<span id="test.foo[5]bar" class="test.foo[5]bar"></span>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								<foo_bar id="foobar">test element</foo_bar>
 | 
				
			||||||
 | 
							</form>
 | 
				
			||||||
 | 
							<b id="floatTest">Float test.</b>
 | 
				
			||||||
 | 
							<iframe id="iframe" name="iframe"></iframe>
 | 
				
			||||||
 | 
							<form id="lengthtest">
 | 
				
			||||||
 | 
								<input type="text" id="length" name="test"/>
 | 
				
			||||||
 | 
								<input type="text" id="idTest" name="id"/>
 | 
				
			||||||
 | 
							</form>
 | 
				
			||||||
 | 
							<table id="table"></table>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							<form id="name-tests">
 | 
				
			||||||
 | 
								<!-- Inputs with a grouped name attribute. -->
 | 
				
			||||||
 | 
								<input name="types[]" id="types_all" type="checkbox" value="all" />
 | 
				
			||||||
 | 
								<input name="types[]" id="types_anime" type="checkbox" value="anime" />
 | 
				
			||||||
 | 
								<input name="types[]" id="types_movie" type="checkbox" value="movie" />
 | 
				
			||||||
 | 
							</form>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							<form id="testForm" action="#" method="get">
 | 
				
			||||||
 | 
								<textarea name="T3" rows="2" cols="15">?
 | 
				
			||||||
 | 
					Z</textarea>
 | 
				
			||||||
 | 
								<input type="hidden" name="H1" value="x" />
 | 
				
			||||||
 | 
								<input type="hidden" name="H2" />
 | 
				
			||||||
 | 
								<input name="PWD" type="password" value="" />
 | 
				
			||||||
 | 
								<input name="T1" type="text" />
 | 
				
			||||||
 | 
								<input name="T2" type="text" value="YES" readonly="readonly" />
 | 
				
			||||||
 | 
								<input type="checkbox" name="C1" value="1" />
 | 
				
			||||||
 | 
								<input type="checkbox" name="C2" />
 | 
				
			||||||
 | 
								<input type="radio" name="R1" value="1" />
 | 
				
			||||||
 | 
								<input type="radio" name="R1" value="2" />
 | 
				
			||||||
 | 
								<input type="text" name="My Name" value="me" />
 | 
				
			||||||
 | 
								<input type="reset" name="reset" value="NO" />
 | 
				
			||||||
 | 
								<select name="S1">
 | 
				
			||||||
 | 
									<option value="abc">ABC</option>
 | 
				
			||||||
 | 
									<option value="abc">ABC</option>
 | 
				
			||||||
 | 
									<option value="abc">ABC</option>
 | 
				
			||||||
 | 
								</select>
 | 
				
			||||||
 | 
								<select name="S2" multiple="multiple" size="3">
 | 
				
			||||||
 | 
									<option value="abc">ABC</option>
 | 
				
			||||||
 | 
									<option value="abc">ABC</option>
 | 
				
			||||||
 | 
									<option value="abc">ABC</option>
 | 
				
			||||||
 | 
								</select>
 | 
				
			||||||
 | 
								<select name="S3">
 | 
				
			||||||
 | 
									<option selected="selected">YES</option>
 | 
				
			||||||
 | 
								</select>
 | 
				
			||||||
 | 
								<select name="S4">
 | 
				
			||||||
 | 
									<option value="" selected="selected">NO</option>
 | 
				
			||||||
 | 
								</select>
 | 
				
			||||||
 | 
								<input type="submit" name="sub1" value="NO" />
 | 
				
			||||||
 | 
								<input type="submit" name="sub2" value="NO" />
 | 
				
			||||||
 | 
								<input type="image" name="sub3" value="NO" />
 | 
				
			||||||
 | 
								<button name="sub4" type="submit" value="NO">NO</button>
 | 
				
			||||||
 | 
								<input name="D1" type="text" value="NO" disabled="disabled" />
 | 
				
			||||||
 | 
								<input type="checkbox" checked="checked" disabled="disabled" name="D2" value="NO" />
 | 
				
			||||||
 | 
								<input type="radio" name="D3" value="NO" checked="checked" disabled="disabled" />
 | 
				
			||||||
 | 
								<select name="D4" disabled="disabled">
 | 
				
			||||||
 | 
									<option selected="selected" value="NO">NO</option>
 | 
				
			||||||
 | 
								</select>
 | 
				
			||||||
 | 
								<input id="list-test" type="text" />
 | 
				
			||||||
 | 
								<datalist id="datalist">
 | 
				
			||||||
 | 
									<option value="option"></option>
 | 
				
			||||||
 | 
								</datalist>
 | 
				
			||||||
 | 
							</form>
 | 
				
			||||||
 | 
							<div id="moretests">
 | 
				
			||||||
 | 
								<form>
 | 
				
			||||||
 | 
									<div id="checkedtest" style="display:none;">
 | 
				
			||||||
 | 
										<input type="radio" name="checkedtestradios" checked="checked"/>
 | 
				
			||||||
 | 
										<input type="radio" name="checkedtestradios" value="on"/>
 | 
				
			||||||
 | 
										<input type="checkbox" name="checkedtestcheckboxes" checked="checked"/>
 | 
				
			||||||
 | 
										<input type="checkbox" name="checkedtestcheckboxes" />
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
								</form>
 | 
				
			||||||
 | 
								<div id="nonnodes"><span>hi</span> there <!-- mon ami --></div>
 | 
				
			||||||
 | 
								<div id="t2037">
 | 
				
			||||||
 | 
									<div><div class="hidden">hidden</div></div>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
								<div id="t6652">
 | 
				
			||||||
 | 
									<div></div>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
								<div id="t12087">
 | 
				
			||||||
 | 
									<input type="hidden" id="el12087" data-comma="0,1"/>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
								<div id="no-clone-exception"><object><embed></embed></object></div>
 | 
				
			||||||
 | 
								<div id="names-group">
 | 
				
			||||||
 | 
									<span id="name-is-example" name="example"></span>
 | 
				
			||||||
 | 
									<span id="name-is-div" name="div"></span>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
								<script id="script-no-src"></script>
 | 
				
			||||||
 | 
								<script id="script-src" src="data/empty.js"></script>
 | 
				
			||||||
 | 
								<div id="id-name-tests">
 | 
				
			||||||
 | 
									<a id="tName1ID" name="tName1"><span></span></a>
 | 
				
			||||||
 | 
									<a id="tName2ID" name="tName2"><span></span></a>
 | 
				
			||||||
 | 
									<div id="tName1"><span id="tName1-span">C</span></div>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							<div id="tabindex-tests">
 | 
				
			||||||
 | 
								<ol id="listWithTabIndex" tabindex="5">
 | 
				
			||||||
 | 
									<li id="foodWithNegativeTabIndex" tabindex="-1">Rice</li>
 | 
				
			||||||
 | 
									<li id="foodNoTabIndex">Beans</li>
 | 
				
			||||||
 | 
									<li>Blinis</li>
 | 
				
			||||||
 | 
									<li>Tofu</li>
 | 
				
			||||||
 | 
								</ol>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								<div id="divWithNoTabIndex">I'm hungry. I should...</div>
 | 
				
			||||||
 | 
								<span>...</span><a href="#" id="linkWithNoTabIndex">Eat lots of food</a><span>...</span> |
 | 
				
			||||||
 | 
								<span>...</span><a href="#" id="linkWithTabIndex" tabindex="2">Eat a little food</a><span>...</span> |
 | 
				
			||||||
 | 
								<span>...</span><a href="#" id="linkWithNegativeTabIndex" tabindex="-1">Eat no food</a><span>...</span>
 | 
				
			||||||
 | 
								<span>...</span><a id="linkWithNoHrefWithNoTabIndex">Eat a burger</a><span>...</span>
 | 
				
			||||||
 | 
								<span>...</span><a id="linkWithNoHrefWithTabIndex" tabindex="1">Eat some funyuns</a><span>...</span>
 | 
				
			||||||
 | 
								<span>...</span><a id="linkWithNoHrefWithNegativeTabIndex" tabindex="-1">Eat some funyuns</a><span>...</span>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							<div id="liveHandlerOrder">
 | 
				
			||||||
 | 
								<span id="liveSpan1"><a href="#" id="liveLink1"></a></span>
 | 
				
			||||||
 | 
								<span id="liveSpan2"><a href="#" id="liveLink2"></a></span>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							<div id="siblingTest">
 | 
				
			||||||
 | 
								<em id="siblingfirst">1</em>
 | 
				
			||||||
 | 
								<em id="siblingnext">2</em>
 | 
				
			||||||
 | 
								<em id="siblingthird">
 | 
				
			||||||
 | 
									<em id="siblingchild">
 | 
				
			||||||
 | 
										<em id="siblinggrandchild">
 | 
				
			||||||
 | 
											<em id="siblinggreatgrandchild"></em>
 | 
				
			||||||
 | 
										</em>
 | 
				
			||||||
 | 
									</em>
 | 
				
			||||||
 | 
								</em>
 | 
				
			||||||
 | 
								<span id="siblingspan"></span>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
						</dl>
 | 
				
			||||||
 | 
						<br id="last"/>
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
							
								
								
									
										9597
									
								
								public/vendor/sizzle/test/jquery.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9597
									
								
								public/vendor/sizzle/test/jquery.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										244
									
								
								public/vendor/sizzle/test/libs/qunit/qunit.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										244
									
								
								public/vendor/sizzle/test/libs/qunit/qunit.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,244 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * QUnit v1.12.0 - A JavaScript Unit Testing Framework
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * http://qunitjs.com
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright 2012 jQuery Foundation and other contributors
 | 
				
			||||||
 | 
					 * Released under the MIT license.
 | 
				
			||||||
 | 
					 * http://jquery.org/license
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Font Family and Sizes */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
 | 
				
			||||||
 | 
						font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
 | 
				
			||||||
 | 
					#qunit-tests { font-size: smaller; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Resets */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
 | 
				
			||||||
 | 
						margin: 0;
 | 
				
			||||||
 | 
						padding: 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Header */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-header {
 | 
				
			||||||
 | 
						padding: 0.5em 0 0.5em 1em;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						color: #8699a4;
 | 
				
			||||||
 | 
						background-color: #0d3349;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						font-size: 1.5em;
 | 
				
			||||||
 | 
						line-height: 1em;
 | 
				
			||||||
 | 
						font-weight: normal;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						border-radius: 5px 5px 0 0;
 | 
				
			||||||
 | 
						-moz-border-radius: 5px 5px 0 0;
 | 
				
			||||||
 | 
						-webkit-border-top-right-radius: 5px;
 | 
				
			||||||
 | 
						-webkit-border-top-left-radius: 5px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-header a {
 | 
				
			||||||
 | 
						text-decoration: none;
 | 
				
			||||||
 | 
						color: #c2ccd1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-header a:hover,
 | 
				
			||||||
 | 
					#qunit-header a:focus {
 | 
				
			||||||
 | 
						color: #fff;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-testrunner-toolbar label {
 | 
				
			||||||
 | 
						display: inline-block;
 | 
				
			||||||
 | 
						padding: 0 .5em 0 .1em;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-banner {
 | 
				
			||||||
 | 
						height: 5px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-testrunner-toolbar {
 | 
				
			||||||
 | 
						padding: 0.5em 0 0.5em 2em;
 | 
				
			||||||
 | 
						color: #5E740B;
 | 
				
			||||||
 | 
						background-color: #eee;
 | 
				
			||||||
 | 
						overflow: hidden;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-userAgent {
 | 
				
			||||||
 | 
						padding: 0.5em 0 0.5em 2.5em;
 | 
				
			||||||
 | 
						background-color: #2b81af;
 | 
				
			||||||
 | 
						color: #fff;
 | 
				
			||||||
 | 
						text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-modulefilter-container {
 | 
				
			||||||
 | 
						float: right;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Tests: Pass/Fail */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-tests {
 | 
				
			||||||
 | 
						list-style-position: inside;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-tests li {
 | 
				
			||||||
 | 
						padding: 0.4em 0.5em 0.4em 2.5em;
 | 
				
			||||||
 | 
						border-bottom: 1px solid #fff;
 | 
				
			||||||
 | 
						list-style-position: inside;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running  {
 | 
				
			||||||
 | 
						display: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-tests li strong {
 | 
				
			||||||
 | 
						cursor: pointer;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-tests li a {
 | 
				
			||||||
 | 
						padding: 0.5em;
 | 
				
			||||||
 | 
						color: #c2ccd1;
 | 
				
			||||||
 | 
						text-decoration: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#qunit-tests li a:hover,
 | 
				
			||||||
 | 
					#qunit-tests li a:focus {
 | 
				
			||||||
 | 
						color: #000;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-tests li .runtime {
 | 
				
			||||||
 | 
						float: right;
 | 
				
			||||||
 | 
						font-size: smaller;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.qunit-assert-list {
 | 
				
			||||||
 | 
						margin-top: 0.5em;
 | 
				
			||||||
 | 
						padding: 0.5em;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						background-color: #fff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						border-radius: 5px;
 | 
				
			||||||
 | 
						-moz-border-radius: 5px;
 | 
				
			||||||
 | 
						-webkit-border-radius: 5px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.qunit-collapsed {
 | 
				
			||||||
 | 
						display: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-tests table {
 | 
				
			||||||
 | 
						border-collapse: collapse;
 | 
				
			||||||
 | 
						margin-top: .2em;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-tests th {
 | 
				
			||||||
 | 
						text-align: right;
 | 
				
			||||||
 | 
						vertical-align: top;
 | 
				
			||||||
 | 
						padding: 0 .5em 0 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-tests td {
 | 
				
			||||||
 | 
						vertical-align: top;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-tests pre {
 | 
				
			||||||
 | 
						margin: 0;
 | 
				
			||||||
 | 
						white-space: pre-wrap;
 | 
				
			||||||
 | 
						word-wrap: break-word;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-tests del {
 | 
				
			||||||
 | 
						background-color: #e0f2be;
 | 
				
			||||||
 | 
						color: #374e0c;
 | 
				
			||||||
 | 
						text-decoration: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-tests ins {
 | 
				
			||||||
 | 
						background-color: #ffcaca;
 | 
				
			||||||
 | 
						color: #500;
 | 
				
			||||||
 | 
						text-decoration: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*** Test Counts */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-tests b.counts                       { color: black; }
 | 
				
			||||||
 | 
					#qunit-tests b.passed                       { color: #5E740B; }
 | 
				
			||||||
 | 
					#qunit-tests b.failed                       { color: #710909; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-tests li li {
 | 
				
			||||||
 | 
						padding: 5px;
 | 
				
			||||||
 | 
						background-color: #fff;
 | 
				
			||||||
 | 
						border-bottom: none;
 | 
				
			||||||
 | 
						list-style-position: inside;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*** Passing Styles */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-tests li li.pass {
 | 
				
			||||||
 | 
						color: #3c510c;
 | 
				
			||||||
 | 
						background-color: #fff;
 | 
				
			||||||
 | 
						border-left: 10px solid #C6E746;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-tests .pass                          { color: #528CE0; background-color: #D2E0E6; }
 | 
				
			||||||
 | 
					#qunit-tests .pass .test-name               { color: #366097; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-tests .pass .test-actual,
 | 
				
			||||||
 | 
					#qunit-tests .pass .test-expected           { color: #999999; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-banner.qunit-pass                    { background-color: #C6E746; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*** Failing Styles */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-tests li li.fail {
 | 
				
			||||||
 | 
						color: #710909;
 | 
				
			||||||
 | 
						background-color: #fff;
 | 
				
			||||||
 | 
						border-left: 10px solid #EE5757;
 | 
				
			||||||
 | 
						white-space: pre;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-tests > li:last-child {
 | 
				
			||||||
 | 
						border-radius: 0 0 5px 5px;
 | 
				
			||||||
 | 
						-moz-border-radius: 0 0 5px 5px;
 | 
				
			||||||
 | 
						-webkit-border-bottom-right-radius: 5px;
 | 
				
			||||||
 | 
						-webkit-border-bottom-left-radius: 5px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-tests .fail                          { color: #000000; background-color: #EE5757; }
 | 
				
			||||||
 | 
					#qunit-tests .fail .test-name,
 | 
				
			||||||
 | 
					#qunit-tests .fail .module-name             { color: #000000; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-tests .fail .test-actual             { color: #EE5757; }
 | 
				
			||||||
 | 
					#qunit-tests .fail .test-expected           { color: green;   }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-banner.qunit-fail                    { background-color: #EE5757; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Result */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-testresult {
 | 
				
			||||||
 | 
						padding: 0.5em 0.5em 0.5em 2.5em;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						color: #2b81af;
 | 
				
			||||||
 | 
						background-color: #D2E0E6;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						border-bottom: 1px solid white;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#qunit-testresult .module-name {
 | 
				
			||||||
 | 
						font-weight: bold;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Fixture */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#qunit-fixture {
 | 
				
			||||||
 | 
						position: absolute;
 | 
				
			||||||
 | 
						top: -10000px;
 | 
				
			||||||
 | 
						left: -10000px;
 | 
				
			||||||
 | 
						width: 1000px;
 | 
				
			||||||
 | 
						height: 1000px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										2212
									
								
								public/vendor/sizzle/test/libs/qunit/qunit.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2212
									
								
								public/vendor/sizzle/test/libs/qunit/qunit.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										95
									
								
								public/vendor/sizzle/test/unit/extending.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								public/vendor/sizzle/test/unit/extending.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,95 @@
 | 
				
			|||||||
 | 
					module("extending", { teardown: moduleTeardown });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test("custom pseudos", function() {
 | 
				
			||||||
 | 
						expect( 6 );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Sizzle.selectors.filters.foundation = Sizzle.selectors.filters.root;
 | 
				
			||||||
 | 
						deepEqual( Sizzle(":foundation"), [ document.documentElement ], "Copy element filter with new name" );
 | 
				
			||||||
 | 
						delete Sizzle.selectors.filters.foundation;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Sizzle.selectors.setFilters.primary = Sizzle.selectors.setFilters.first;
 | 
				
			||||||
 | 
						t( "Copy set filter with new name", "div:primary", ["qunit"] );
 | 
				
			||||||
 | 
						delete Sizzle.selectors.setFilters.primary;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Sizzle.selectors.filters.aristotlean = Sizzle.selectors.createPseudo(function() {
 | 
				
			||||||
 | 
							return function( elem ) {
 | 
				
			||||||
 | 
								return !!elem.id;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
						t( "Custom element filter", "#foo :aristotlean", [ "sndp", "en", "yahoo", "sap", "anchor2", "simon" ] );
 | 
				
			||||||
 | 
						delete Sizzle.selectors.filters.aristotlean;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Sizzle.selectors.filters.endswith = Sizzle.selectors.createPseudo(function( text ) {
 | 
				
			||||||
 | 
							return function( elem ) {
 | 
				
			||||||
 | 
								return Sizzle.getText( elem ).slice( -text.length ) === text;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
						t( "Custom element filter with argument", "a:endswith(ogle)", ["google"] );
 | 
				
			||||||
 | 
						delete Sizzle.selectors.filters.endswith;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Sizzle.selectors.setFilters.second = Sizzle.selectors.createPseudo(function() {
 | 
				
			||||||
 | 
							return Sizzle.selectors.createPseudo(function( seed, matches ) {
 | 
				
			||||||
 | 
								if ( seed[1] ) {
 | 
				
			||||||
 | 
									matches[1] = seed[1];
 | 
				
			||||||
 | 
									seed[1] = false;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
						t( "Custom set filter", "#qunit-fixture p:second", ["ap"] );
 | 
				
			||||||
 | 
						delete Sizzle.selectors.filters.second;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Sizzle.selectors.setFilters.slice = Sizzle.selectors.createPseudo(function( argument ) {
 | 
				
			||||||
 | 
							var bounds = argument.split(":");
 | 
				
			||||||
 | 
							return Sizzle.selectors.createPseudo(function( seed, matches ) {
 | 
				
			||||||
 | 
								var i = bounds[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Match elements found at the specified indexes
 | 
				
			||||||
 | 
								while ( --i >= bounds[0] ) {
 | 
				
			||||||
 | 
									if ( seed[i] ) {
 | 
				
			||||||
 | 
										matches[i] = seed[i];
 | 
				
			||||||
 | 
										seed[i] = false;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
						t( "Custom set filter with argument", "#qunit-fixture p:slice(1:3)", [ "ap", "sndp" ] );
 | 
				
			||||||
 | 
						delete Sizzle.selectors.filters.slice;
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test("backwards-compatible custom pseudos", function() {
 | 
				
			||||||
 | 
						expect( 3 );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Sizzle.selectors.filters.icontains = function( elem, i, match ) {
 | 
				
			||||||
 | 
							return Sizzle.getText( elem ).toLowerCase().indexOf( (match[3] || "").toLowerCase() ) > -1;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						t( "Custom element filter with argument", "a:icontains(THIS BLOG ENTRY)", ["simon1"] );
 | 
				
			||||||
 | 
						delete Sizzle.selectors.filters.icontains;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Sizzle.selectors.setFilters.podium = function( elements, argument ) {
 | 
				
			||||||
 | 
							var count = argument == null || argument === "" ? 3 : +argument;
 | 
				
			||||||
 | 
							return elements.slice( 0, count );
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						// Using TAG as the first token here forces this setMatcher into a fail state
 | 
				
			||||||
 | 
						// Where the descendent combinator was lost
 | 
				
			||||||
 | 
						t( "Custom setFilter", "form#form :PODIUM", ["label-for", "text1", "text2"] );
 | 
				
			||||||
 | 
						t( "Custom setFilter with argument", "#form input:Podium(1)", ["text1"] );
 | 
				
			||||||
 | 
						delete Sizzle.selectors.setFilters.podium;
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test("custom attribute getters", function() {
 | 
				
			||||||
 | 
						expect( 2 );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var original = Sizzle.selectors.attrHandle.hreflang,
 | 
				
			||||||
 | 
							selector = "a:contains('mark')[hreflang='http://diveintomark.org/en']";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Sizzle.selectors.attrHandle.hreflang = function( elem, name ) {
 | 
				
			||||||
 | 
							var href = elem.getAttribute("href"),
 | 
				
			||||||
 | 
								lang = elem.getAttribute( name );
 | 
				
			||||||
 | 
							return lang && ( href + lang );
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						deepEqual( Sizzle(selector, createWithFriesXML()), [], "Custom attrHandle (preferred document)" );
 | 
				
			||||||
 | 
						t( "Custom attrHandle (preferred document)", selector, ["mark"] );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Sizzle.selectors.attrHandle.hreflang = original;
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
							
								
								
									
										1138
									
								
								public/vendor/sizzle/test/unit/selector.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1138
									
								
								public/vendor/sizzle/test/unit/selector.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										169
									
								
								public/vendor/sizzle/test/unit/utilities.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								public/vendor/sizzle/test/unit/utilities.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,169 @@
 | 
				
			|||||||
 | 
					module("utilities", { teardown: moduleTeardown });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function testAttr( doc ) {
 | 
				
			||||||
 | 
						expect( 9 );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var el;
 | 
				
			||||||
 | 
						if ( doc ) {
 | 
				
			||||||
 | 
							// XML
 | 
				
			||||||
 | 
							el = doc.createElement( "input" );
 | 
				
			||||||
 | 
							el.setAttribute( "type", "checkbox" );
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							// Set checked on creation by creating with a fragment
 | 
				
			||||||
 | 
							// See http://jsfiddle.net/8sVgA/1/show/light in oldIE
 | 
				
			||||||
 | 
							el = jQuery( "<input type='checkbox' checked='checked' />" )[0];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Set it again for good measure
 | 
				
			||||||
 | 
						el.setAttribute( "checked", "checked" );
 | 
				
			||||||
 | 
						el.setAttribute( "id", "id" );
 | 
				
			||||||
 | 
						el.setAttribute( "value", "on" );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						strictEqual( Sizzle.attr( el, "nonexistent" ), null, "nonexistent" );
 | 
				
			||||||
 | 
						strictEqual( Sizzle.attr( el, "id" ), "id", "existent" );
 | 
				
			||||||
 | 
						strictEqual( Sizzle.attr( el, "value" ), "on", "value" );
 | 
				
			||||||
 | 
						strictEqual( Sizzle.attr( el, "checked" ), "checked", "boolean" );
 | 
				
			||||||
 | 
						strictEqual( Sizzle.attr( el, "href" ), null, "interpolation risk" );
 | 
				
			||||||
 | 
						strictEqual( Sizzle.attr( el, "constructor" ), null,
 | 
				
			||||||
 | 
							"Object.prototype property \"constructor\" (negative)" );
 | 
				
			||||||
 | 
						strictEqual( Sizzle.attr( el, "watch" ), null,
 | 
				
			||||||
 | 
							"Gecko Object.prototype property \"watch\" (negative)" );
 | 
				
			||||||
 | 
						el.setAttribute( "constructor", "foo" );
 | 
				
			||||||
 | 
						el.setAttribute( "watch", "bar" );
 | 
				
			||||||
 | 
						strictEqual( Sizzle.attr( el, "constructor" ), "foo",
 | 
				
			||||||
 | 
							"Object.prototype property \"constructor\"" );
 | 
				
			||||||
 | 
						strictEqual( Sizzle.attr( el, "watch" ), "bar",
 | 
				
			||||||
 | 
							"Gecko Object.prototype property \"watch\"" );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test("Sizzle.attr (HTML)", function() {
 | 
				
			||||||
 | 
						testAttr();
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test("Sizzle.attr (XML)", function() {
 | 
				
			||||||
 | 
						testAttr( jQuery.parseXML("<root/>") );
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test("Sizzle.contains", function() {
 | 
				
			||||||
 | 
						expect( 16 );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var container = document.getElementById("nonnodes"),
 | 
				
			||||||
 | 
							element = container.firstChild,
 | 
				
			||||||
 | 
							text = element.nextSibling,
 | 
				
			||||||
 | 
							nonContained = container.nextSibling,
 | 
				
			||||||
 | 
							detached = document.createElement("a");
 | 
				
			||||||
 | 
						ok( element && element.nodeType === 1, "preliminary: found element" );
 | 
				
			||||||
 | 
						ok( text && text.nodeType === 3, "preliminary: found text" );
 | 
				
			||||||
 | 
						ok( nonContained, "preliminary: found non-descendant" );
 | 
				
			||||||
 | 
						ok( Sizzle.contains(container, element), "child" );
 | 
				
			||||||
 | 
						ok( Sizzle.contains(container.parentNode, element), "grandchild" );
 | 
				
			||||||
 | 
						ok( Sizzle.contains(container, text), "text child" );
 | 
				
			||||||
 | 
						ok( Sizzle.contains(container.parentNode, text), "text grandchild" );
 | 
				
			||||||
 | 
						ok( !Sizzle.contains(container, container), "self" );
 | 
				
			||||||
 | 
						ok( !Sizzle.contains(element, container), "parent" );
 | 
				
			||||||
 | 
						ok( !Sizzle.contains(container, nonContained), "non-descendant" );
 | 
				
			||||||
 | 
						ok( !Sizzle.contains(container, document), "document" );
 | 
				
			||||||
 | 
						ok( !Sizzle.contains(container, document.documentElement), "documentElement (negative)" );
 | 
				
			||||||
 | 
						ok( !Sizzle.contains(container, null), "Passing null does not throw an error" );
 | 
				
			||||||
 | 
						ok( Sizzle.contains(document, document.documentElement), "documentElement (positive)" );
 | 
				
			||||||
 | 
						ok( Sizzle.contains(document, element), "document container (positive)" );
 | 
				
			||||||
 | 
						ok( !Sizzle.contains(document, detached), "document container (negative)" );
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if ( jQuery("<svg xmlns='http://www.w3.org/2000/svg' version='1.1' height='1' width='1'><g/></svg>")[0].firstChild ) {
 | 
				
			||||||
 | 
						test("Sizzle.contains in SVG (jQuery #10832)", function() {
 | 
				
			||||||
 | 
							expect( 4 );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							var svg = jQuery(
 | 
				
			||||||
 | 
								"<svg xmlns='http://www.w3.org/2000/svg' version='1.1' height='1' width='1'>" +
 | 
				
			||||||
 | 
									"<g><circle cx='1' cy='1' r='1' /></g>" +
 | 
				
			||||||
 | 
								"</svg>"
 | 
				
			||||||
 | 
							).appendTo("#qunit-fixture")[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ok( Sizzle.contains( svg, svg.firstChild ), "root child" );
 | 
				
			||||||
 | 
							ok( Sizzle.contains( svg.firstChild, svg.firstChild.firstChild ), "element child" );
 | 
				
			||||||
 | 
							ok( Sizzle.contains( svg, svg.firstChild.firstChild ), "root granchild" );
 | 
				
			||||||
 | 
							ok( !Sizzle.contains( svg.firstChild.firstChild, svg.firstChild ), "parent (negative)" );
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test("Sizzle.uniqueSort", function() {
 | 
				
			||||||
 | 
						expect( 14 );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						function Arrayish( arr ) {
 | 
				
			||||||
 | 
							var i = this.length = arr.length;
 | 
				
			||||||
 | 
							while ( i-- ) {
 | 
				
			||||||
 | 
								this[ i ] = arr[ i ];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						Arrayish.prototype = {
 | 
				
			||||||
 | 
							slice: [].slice,
 | 
				
			||||||
 | 
							sort: [].sort,
 | 
				
			||||||
 | 
							splice: [].splice
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var i, tests,
 | 
				
			||||||
 | 
							detached = [],
 | 
				
			||||||
 | 
							body = document.body,
 | 
				
			||||||
 | 
							fixture = document.getElementById("qunit-fixture"),
 | 
				
			||||||
 | 
							detached1 = document.createElement("p"),
 | 
				
			||||||
 | 
							detached2 = document.createElement("ul"),
 | 
				
			||||||
 | 
							detachedChild = detached1.appendChild( document.createElement("a") ),
 | 
				
			||||||
 | 
							detachedGrandchild = detachedChild.appendChild( document.createElement("b") );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for ( i = 0; i < 12; i++ ) {
 | 
				
			||||||
 | 
							detached.push( document.createElement("li") );
 | 
				
			||||||
 | 
							detached[i].id = "detached" + i;
 | 
				
			||||||
 | 
							detached2.appendChild( document.createElement("li") ).id = "detachedChild" + i;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tests = {
 | 
				
			||||||
 | 
							"Empty": {
 | 
				
			||||||
 | 
								input: [],
 | 
				
			||||||
 | 
								expected: []
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"Single-element": {
 | 
				
			||||||
 | 
								input: [ fixture ],
 | 
				
			||||||
 | 
								expected: [ fixture ]
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"No duplicates": {
 | 
				
			||||||
 | 
								input: [ fixture, body ],
 | 
				
			||||||
 | 
								expected: [ body, fixture ]
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"Duplicates": {
 | 
				
			||||||
 | 
								input: [ body, fixture, fixture, body ],
 | 
				
			||||||
 | 
								expected: [ body, fixture ]
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"Detached": {
 | 
				
			||||||
 | 
								input: detached.slice( 0 ),
 | 
				
			||||||
 | 
								expected: detached.slice( 0 )
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"Detached children": {
 | 
				
			||||||
 | 
								input: [
 | 
				
			||||||
 | 
									detached2.childNodes[0],
 | 
				
			||||||
 | 
									detached2.childNodes[1],
 | 
				
			||||||
 | 
									detached2.childNodes[2],
 | 
				
			||||||
 | 
									detached2.childNodes[3]
 | 
				
			||||||
 | 
								],
 | 
				
			||||||
 | 
								expected: [
 | 
				
			||||||
 | 
									detached2.childNodes[0],
 | 
				
			||||||
 | 
									detached2.childNodes[1],
 | 
				
			||||||
 | 
									detached2.childNodes[2],
 | 
				
			||||||
 | 
									detached2.childNodes[3]
 | 
				
			||||||
 | 
								]
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"Attached/detached mixture": {
 | 
				
			||||||
 | 
								input: [ detached1, fixture, detached2, document, detachedChild, body, detachedGrandchild ],
 | 
				
			||||||
 | 
								expected: [ document, body, fixture ],
 | 
				
			||||||
 | 
								length: 3
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						jQuery.each( tests, function( label, test ) {
 | 
				
			||||||
 | 
							var length = test.length || test.input.length;
 | 
				
			||||||
 | 
							deepEqual( Sizzle.uniqueSort( test.input ).slice( 0, length ), test.expected, label + " (array)" );
 | 
				
			||||||
 | 
							deepEqual( Sizzle.uniqueSort( new Arrayish(test.input) ).slice( 0, length ), test.expected, label + " (quasi-array)" );
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					testIframeWithCallback( "Sizzle.uniqueSort works cross-window (jQuery #14381)", "mixed_sort.html", deepEqual );
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user