My favorites | Sign in
Project Logo
             
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "DTD/xhtml1-transitional.dtd">

<!--
Copyright 2007, Google Inc.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of Google Inc. nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->

<html>
<head>
<title>Gears FAQ</title>
<link rel="stylesheet" type="text/css" href="gears.css" />
</head>

<body>
<h1>Gears FAQ</h1>

<div id="pagecontent">

<h1 id="Google__Gearsfor__Web__UsersTOC">Gears for Web Users</h1>
<p>
<div style="padding:0px 40px 0px 40px">
<a href="#whySeeConnectionError">Why do I see a connection error when I try to install?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#isGearsInstalled">How do I know if Gears is installed on a computer I am using?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#installOnAnotherMozillaBrowser">How do I install Gears on another Mozilla based browser?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#runGearsOn64Bit">How do I run Gears on my 64-bit system?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#uninstall">How do I uninstall Gears?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#anyAppOffline">Does Gears make any application work offline?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#whatIsDialog">Why do I see a dialog asking if I want to allow a website to use Gears?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#geolocationOnMobile">Does Gears Geolocation work on my mobile device?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

</div>

</p>


<h1 id="Getting__StartedTOC">Getting Started</h1>
<p>
<div style="padding:0px 40px 0px 40px">
<a href="#whatIsGears">What is Gears?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#howToContribute">How do I contribute to Gears?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#status">What is the status of Gears?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#automaticallyOffline">Does Gears automatically make my web application work offline?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#supportedSystems">What browsers and operating systems are supported by Gears?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#needLicense">Do I need a license to use Gears?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#howToBuildApplication">How do I build an application with Gears?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#greatIdea">I have a great idea for Gears. Whom should I contact?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

</div>

</p>

<h1 id="Developing__With__GearsTOC">Developing With Gears</h1>
<p>
<div style="padding:0px 40px 0px 40px">
<a href="#canGearsServeScripts">Can Gears LocalServer serve up scripting files like PHP or JSP?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#sqliteTool">Is there a tool to interactively manage and query Gears' SQLite database tables?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#deteDatabases">How do I delete databases that were created from the Gears API?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#prepareWorkerPoolCode">How do I make JavaScript source code available to a child WorkerPool during initialization?</a>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#separatePorts">If I have two applications on separate ports, will they have the same LocalServer and Database files?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#crossOriginWorker">What is a cross-origin worker? What is it useful for? How do I use it?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#multipleWorkersAccessingDB">Do I need to protect from multiple workers editing the database at once?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#storeURLParameters">Does LocalServer store URL parameters?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#howToOfflineCrossOrigin">How do I 'offline' a cross-origin resource?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#queryLocalServer">Is there a tool to interactively manage and query Gears' LocalServer?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#workerPoolDOMAccess">Do WorkerPool workers have access to the DOM document object?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#isOnlineFunction">Is there an isOnline function in Gears to check whether the application is online? Do you plan to have one? Can you provide code for offline detection?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#automaticOffline">Does Gears automatically make my web application work offline?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#howMakeOffilne">Gears lets my web application work offline, right? How do I do that?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#howStoreData">Gears lets my web application store data on the user's computer, right? How do I do that?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#howRunBackground">Gears lets my web application run code in the background, right? How do I do that?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#linuxCompatible">What does Gears require to be compatible with my Linux system?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#whereAreFiles">Where are Gears files stored?</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

</div>

</p>

<h1 id="Best__PracticesTOC">Best Practices</h1>
<p>
<div style="padding:0px 40px 0px 40px">
<a href="#bestPracticeStartGears">Best Practices for Starting With Gears</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#offlineArchitectures">Best Practices for Offline Architectures</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#offlineDetection">Best Practices for Online/Offline Detection</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#bestGearsPerms">Best Practices for Gears Permissioning</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#detectingGears">Best Practices for Installation and Detection</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#cachingDifferentDomain">Best Practices for Using LocalServer With Web Applications Spread Across Different Hosts</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#bestPracticeDB">Best Practices for Database Performance and Reliability</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#offlineUI">Best Practices for Offline User Interfaces</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#maintainWorkers">Best Practices for Maintainable Workers</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#choosingNames">Best Practices for Choosing Names for Databases and LocalServers</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#storingData">Best Practices for Storing Data on Users' Machines</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#desktopShortcuts">Best Practices for Desktop Shortcuts</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#versionDBSchema">Best Practices for Versioning Database Schema</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#useMRS">Best Practices for LocalServer</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#syncing">Best Practices for Syncing</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="#webAppAsDesktop">Best Practices for Giving Web Applications Similar Features to Desktop Applications</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>
</div>
</p>

<h1 id="Articles__And__TutorialsTOC">Articles And Tutorials</h1>
<p>
<div style="padding:0px 40px 0px 40px">
<a href="articles/gearsmonkey.html">GearsMonkey: Gears + Greasemonkey to take Wikipedia offline</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="articles/take_app_offline.html">Taking Web Applications Offline with Gears</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="articles/performant_offline_app.html">Using Google Base and Gears for a Performant, Offline Experience</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

<a href="articles/running_man.html">RunningMan: A location-aware stopwatch for Android</a>
<br/>
<span style="line-height:4px">
&nbsp;<br/>
</span>

</div>

</p>

<hr>

<h2 id="Google__Gearsfor__Web__Users">Gears for Web Users</h2>

<dt id="whySeeConnectionError">Why do I see a connection error when I try to install?
</dt>

<dd>
<p>
Listed below are several possible causes for the connection error you're receiving. Please determine which of these causes may be applicable to you and follow the instructions to resolve the problem.
</p>
<ul>
<li>
Your firewall, anti-virus software, or proxy is preventing the program from accessing the Internet. In this case, you need to add it to your security software's exceptions list. If you're using Windows firewall, you can add this program by following these steps:
<ol>
<li>
Click "Start" in your Windows Taskbar and choose "Control Panel" >
"Windows Firewall."
</li>
<li>
Select the "Exceptions" tab.
</li>
<li>
Click the "Add Program" button.
</li>
<li>
Click "Browse" and select "My Computer" from the left side of the window.
</li>
<li>
Select "Local Disk (C:)" and click "Open."
</li>
<?cs if:Query.isMachine == "1" ?>
<li>
Double-click "Program Files" >
"Google" >
"Common."
</li>
<li>
Select the folder with the highest number and open it.
</li>
<li>
Choose the file "googleupdate.exe."
</li>
<?cs else ?>
<li>
Open "Documents and Settings."
</li>
<li>
Open the folder with your username.
</li>
<li>
Open "Local Settings" >
"Application Data" >
"Google" >
"Update."
</li>
<li>
Select the folder with the highest number and open it.
</li>
<li>
Choose the file "googleupdate.exe."
</li>
<?cs /if ?>
</ol>
<p>
If you're using other firewall software, please visit that program's website for specific instructions to add applications to the exceptions list.
</p>

</li>
<li>
You may not have the latest updates for Windows XP. If you're not currently running Windows XP Service Pack 2, please try upgrading Windows.
</li>
<br />
<li>
You’re on an authenticated proxy server that isn't supported. Currently, we support the Negotiate authentication scheme. This includes both Kerberos and NTLM, depending on what is available. Additionally, proxies using &quot;integrated authentication&quot; are supported, provided that the current user is authorized to go through that proxy. Please determine if you're on a supported proxy server.
</li>
<br />
<li>
Your computer's Background Intelligent Transfer Service (BITS) isn't starting properly. If this is the case, you may want to verify that BITS is correctly configured. To ensure that BITS is enabled, please follow these steps: <ol>
<li>
Click the "Start" button in your Windows taskbar and select "Settings" >
"Control Panel" >
"Administrative Tools" >
"Services."
</li>
<li>
Select "Background Intelligent Transfer Service" from the list.
</li>
<li>
Right-click “Background Intelligent Transfer Service” and choose "Properties" from the menu.
</li>
<li>
From the "General" tab verify that the "Startup" type is set to either "Automatic" or "Manual." Make sure this setting is not "Disabled."
</li>
</ol>
<p>
If you continue to have difficulties with BITS, make sure you have write access to the following folder:
</p>
<p>
C:\Documents and Settings\All Users\Application Data\Microsoft\Network\Downloader\
</p>
<p>
To determine if you have write access, right-click the folder and choose &quot;Properties.&quot; If you see an empty box next to &quot;Read-only&quot; in the &quot;General tab,&quot; you do have write access. If you see a checkmark or a green box, click the box until it's empty and click &quot;OK.&quot; If you're unable to click the box, please speak with your system administrator.
</p>

</li>
</ul>
</dd>



<dt id="isGearsInstalled">
How do I know if Gears is installed on a computer I am using?
</dt>

<dd>
<p>
Occasionally you may wish to know if Gears is installed on a particular computer. For example, you may wish to know if Gears is installed on a computer at an internet cafe, prior to logging in with any sensitive information. Currently, there are two ways to accomplish this:
</p>
<ul>
<li>
Visit the page <a href="http://gears.google.com/" title="http://gears.google.com/">http://gears.google.com/</a>. That page will clearly tell you whether Gears is installed or not.
</li>
<li>
Attempt to access the Gears settings dialog, which is available from the browser's Tools menu if Gears is installed. <li>
<li>
Check the computer directly:
</li>
<ul>
<li>
<b>Windows XP or Vista</b>
<br/>
Open <strong>Add or Remove Programs</strong> (on XP) or <strong>Programs and Features</strong> (on Vista) from the Windows Control Panel. If Gears is not listed, then Gears is not installed.<br/>
</li>
<li>
<b>Mac OS X - Safari</b>
<br/>
In Safari, select Safari &gt; Google Gears Settings.... If the 'Google Gears Settings...' is not listed, then Gears is not installed.
</li>
<li>
<b>Mac OS X or Linux - Firefox</b>
<br/>
In Firefox, select Tools &gt; Extensions (Firefox 1.x) or Tools &gt; Add-ons (Firefox 2.0+) from the menu. If Gears is not listed, then Gears is not installed.
</li>
<li>
<b>Windows Mobile</b>
<br/>
If your particular phone supports it, you can access the list of installed programs by selecting Remove Programs from the Settings page. If Gears is not listed, then Gears is not installed.
</li>
</ul>
</ul>
</dd>



<dt id="installOnAnotherMozillaBrowser">
How do I install Gears on another Mozilla based browser?
</dt>

<dd>
<br/>
There are 3 steps:
<ol>
<li>
Go to the install directory of Gears:<br/>
<b>Mac OS X </b> - ~/Library/Application Support/Firefox/Profiles/&lt;<em>yourprofile</em>&gt;/extensions/{000a9d1c-beef-4f90-9363-039d445309b8}
<br/>
<b>Windows</b> - C:\Program Files\Google\Gears\Firefox
<br/>
<b>Linux</b> - ./mozilla/firefox/&lt;<em>yourprofile</em>&gt;/extensions/{000a9d1c-beef-4f90-9363-039d445309b8}
</li>
<li>
Modify the <em>install.rdf</em> file:
<ol>
<li>
Do a search on any search engine for the GUID of the Mozilla variant you are using. The example below uses Flock's
</li>
<li>
Add this to your <em>install.rdf</em> file under the last &lt;/em:targetApplication&gt; (note: id is the GUID):
<pre class="prettyprint">
&lt;em:targetApplication&gt;
&lt;Description&gt;
&lt;em:id&gt;{a463f10c-3994-11da-9945-000d60ca027b}&lt;/em:id&gt;
&lt;em:maxVersion&gt;6.02&lt;/em:maxVersion&gt;
&lt;em:minVersion&gt;0.2&lt;/em:minVersion&gt;
&lt;/Description&gt;
&lt;/em:targetApplication&gt;
</pre>

</li>
</ol>
<li>
Zip up the contents of the directory, rename the .ZIP to .XPI, drag the .XPI into your Mozilla variant.
</li>
</li>
</ol>
</dd>



<dt id="runGearsOn64Bit">
How do I run Gears on my 64-bit system?
</dt>

<dd>
<p>
There are two ways to do so.
<ol>
<li>
<a href="http://groups.google.com/group/gears-users/browse_thread/thread/4584842dd14a4882" title="64 bit Linux support - Gears | Google Groups">A patch</a> submitted by a user.
</li>
<li>
A plugin called <a href="http://plugindoc.mozdev.org/linux-amd64.html#nswrapper" title="PluginDoc: Linux (x86_64)">nspluginwrapper</a> to use 32-bit browser plugins with x86_64 browsers.
</li>
</ol>
</p>
</dd>



<dt id="uninstall">
How do I uninstall Gears?
</dt>

<dd>
To uninstall Gears, you can follow the instructions here:<a href="http://code.google.com/apis/gears/install.html" title="http://code.google.com/apis/gears/install.html">http://code.google.com/apis/gears/install.html</a>. Once you uninstall Gears, you will no longer have offline access to applications that require Gears.
</dd>



<dt id="anyAppOffline">
Does Gears make any application work offline?
</dt>

<dd>
No. Only web sites that have been specifically designed to use Gears can take advantage of its offline capabilities.
</dd>



<dt id="whatIsDialog">
Why do I see a dialog asking if I want to allow a website to use Gears?
</dt>

<dd>
<p>
Since Gears allows web applications to write to your computer, Gears wants to be sure that the website has your permission to do so. You will see this dialog ever time the website tries to use Gears. If you trust the website and always want to permit it to use Gears, then check "Remember my decision for this site" and click Allow.
</p>
<p>
If you visit a new site that also wants to use Gears, you will see the message and can choose to give the new site permission or not.
</p>
</dd>

<dt id="geolocationOnMobile">
Does Gears Geolocation work on my mobile device?
</dt>

<dd>
<p>
Visit the <a href="http://www.google.com/support/mobile/bin/answer.py?answer=105928">Google Mobile Help Center</a> to learn about Gears Geolocation support on mobile devices.
</p>
</dd>






<hr>

<h2 id="Getting__Started">Getting Started</h2>

<dt id="whatIsGears">
What is Gears?
</dt>

<dd>
<p>
Gears is an open source browser extension that lets developers create web applications that can run offline. Gears provides three key features:
</p>
<ul>
<li>
A local server, to cache and serve application resources (HTML, JavaScript, images, etc.) without needing to contact a server
</li>
<li>
A database, to store and access data from within the browser
</li>
<li>
A worker thread pool, to make web applications more responsive by performing expensive operations in the background
</li>
</ul>
<p>
Gears
</b> is currently an early-access developers' release. It is not yet intended for use by real users in production applications at this time.
</p>
<br />
<p>
If you're a developer interested in using Gears with your application, visit the <a href="http://code.google.com/apis/gears/">Gears Developer Page</a>.
</p>
<p>
If you wish to install Gears on your computer, visit the <a href="http://gears.google.com/">Gears Home Page</a>. Please note, however, that Gears is not yet intended for general use.
</p>
</dd>



<dt id="howToContribute">
How do I contribute to Gears?
</dt>

<dd>
<p>
Go to the <a href="http://code.google.com/p/google-gears/">Google Code Project home for Gears</a>. There is also a <a href="http://code.google.com/p/google-gears/wiki/ContributingToGears">wiki document</a> that explains how to contribute to Gears.
</p>
</dd>



<dt id="status">
What is the status of Gears?
</dt>
<dd>
<p>
Gears is currently a beta product; moreover, it is currently considered to be a developer-only release. When the developer community has had a chance to examine, critique, and improve Gears, a final version suitable for use with production applications will be made available.
</p>
<p>
Gears is open source software, licensed under the New BSD license. Generally speaking, this license allows you to embed the Gears runtime or API in your software, without restriction. You should, of course, consult a lawyer about licensing issues before choosing to embed Gears in your software. There is no restriction on web applications which make use of Gears installations on users' computers.
</p>
<p>
Google is working with a variety of partners to make Gears widely available, and easy for developers to use.
</p>
<p>
For more information, visit the <a href="http://code.google.com/apis/gears/">Gears Developers' Site</a>.
</p>
</dd>



<dt id="automaticallyOffline">
Does Gears automatically make my web application work offline?
</dt>

<dd>
<p>
Gears extends browsers by making new APIs available to JavaScript code. Like all APIs, they must be used explicitly. To take advantage of the offline features provided by Gears, you'll need to add or change code in your web application.
</p>
<br />
<p>
There are three core modules provided by Gears: a <a href="http://code.google.com/apis/gears/api_localserver.html">LocalServer</a> for storing and accessing application pages offline, a <a href="http://code.google.com/apis/gears/api_database.html">Database</a> for storing and accessing application data on the user's computer, and a <a href="http://code.google.com/apis/gears/api_workerpool.html">WorkerPool</a> for performing long-running tasks (such as the code that synchronizes data between your server and users' computers). For more information, follow the links.
</p>
<br />
<p>
A <a href="http://code.google.com/apis/gears/tutorial.html">Gears Tutorial</a> is available that illustrates the basic concepts. You may also find the <a href="http://code.google.com/apis/gears/sample.html">Gears sample applications</a>useful. Source code for these samples can be downloaded in a zip file found on the same page.
</p>
</dd>



<dt id="supportedSystems">
What browsers and operating systems are supported by Gears?
</dt>

<dd>
<p>
Gears works on the following browsers:
</p>
<ul>
<li>
Apple Mac OS X (10.4 or higher, G4, G5 or Intel Processor)
</li>
<ul>
<li>
Firefox 1.5 or higher
</li>
<li>
Safari 3.1.1 or higher (requires OS X Tiger 10.4.11+ or Leopard 10.5.3+, G4, G5 or Intel Processor)
</li>
</ul>
<li>
Linux (<a href="http://code.google.com/support/bin/answer.py?answer=71866&topic=11630">Requirements</a>)
</li>
<ul>
<li>
Firefox 1.5 or higher
</li>
</ul>
<li>
Microsoft Windows (XP or higher)
</li>
<ul>
<li>
Firefox 1.5 or higher
</li>
<li>
Internet Explorer 6 or higher
</li>
<li>
Google Chrome
</li>
</ul>
<li>
Microsoft Windows Mobile (5 or higher)
</li>
<ul>
<li>
Internet Explorer 4.01 or higher
</li>
<li>
Opera Mobile 9.51 (Presto build 2.1.0+) (Windows Mobile 6 touchscreen devices only)
</li>
<li>
The following devices are not supported
</li>
<ul>
<li>
Samsung i320 and i320N
</li>
<li>
Orange SPV C600
</li>
<li>
Motorola Q
</li>
</ul>
</ul>
<li>
Android 1.0
</li>
</ul>
</dd>



<dt id="needLicense">
Do I need a license to use Gears?
</dt>

<dd>
<p>
Gears is open source software, licensed under the <a href="http://www.opensource.org/licenses/bsd-license.php">New BSD license</a>
. Generally speaking, this license is very permissive. You should, of course, always consult an attorney if you have any questions about software licensing.
</p>
<p>
There are generally two ways to use Gears: by embedding the API or runtime software in an application you distribute to end users, or by writing a web application which makes use of installations of Gears on end-users' computers.
</p>
<p>
The <a href="http://www.opensource.org/licenses/bsd-license.php">New BSD license</a>
allows you to embed the Gears runtime or API in your software, with very minimal restrictions. There are no restrictions on web applications which make use of Gears installations on users' computers.
</p>
</dd>



<dt id="howToBuildApplication">
How do I build an application with Gears?
</dt>

<dd>
<p>
Enhancing your web application with offline functionality can be challenging at first. Here are some resources to help you get started:
</p>
<ul>
<li>
The <a href="http://code.google.com/apis/gears/tutorial.html">Gears Tutorial</a>
will walk you through the process of building a very basic, static application.
</li>
<li>
The <a href="http://code.google.com/apis/gears/sample.html">Gears Samples</a>
demonstrate how to use each of the core APIs included in Gears, with source code.
</li>
<li>
Read <a href="http://code.google.com/apis/gears/architecture.html">Choosing an Offline Application Architecture</a>
to learn about design decisions you may encounter.
</li>
<li>
When you're ready to start debugging, check out the <a href="http://code.google.com/apis/gears/tools.html">debugging tools</a>
.
</li>
</ul>
<p>
If those resources don't answer your question, you can also contact other Gears developers over at the <a href="http://groups.google.com/group/gears-users">Gears Discussion Group</a>
.
</p>
</dd>



<dt id="greatIdea">
I have a great idea for Gears. Whom should I contact?
</dt>

<dd>
<p>
We'd love to hear your feedback and suggestions! Gears is open source software, so you should feel free to join our community. If you have a cool new idea you'd like to discuss, you should join our <a href="http://groups.google.com/group/gears-users">Google Group</a>
and post your comment there.
</p>
<p>
The Gears discussion group is intended for all topics, so don't be shy! You can post there whether your idea is about an application you'd like to build, or an enhancement or feature you'd like to see in Gears. Perhaps most importantly, you can also post there if you're having problems using Gears in an application you're building. The Gears discussion group is an open forum. Developers help each other, but the group also includes Google employees working on Gears who post regularly.
</p>
<p>
If you're interested in obtaining the source code for Gears and making some enhancements of your own, you should also visit the <a href="http://code.google.com/p/google-gears/">Gears Contributors Site</a>.
</p>
</dd>

<hr>

<h2 id="Developing__With__Gears">Developing With Gears</h2>


<dt id="canGearsServeScripts">
Can Gears LocalServer serve up scripting files like PHP or JSP?
</dt>

<dd>
<p>
No. Gears LocalServer is simply a static content cache that intercepts URL requests to static content and serves them locally. The LocalServer does not provide the capability to interpret any server-side scripting.
</p>
</dd>



<dt id="sqliteTool">
Is there a tool to interactively manage and query Gears' SQLite database tables?
</dt>

<dd>
<p>
Yes. The Database Query Tool allows developers to interface with SQLite interactively via SQL commands. It can be downloaded at <a href='http://code.google.com/apis/gears/tools.html'>http://code.google.com/apis/gears/tools.html</a>. Simply copy the "dbquery.html" file to your server directory and visit the URL in your browser, and you can start issuing SQL commands to the embedded SQLite. There is also a similar third party tool, called <a href="http://code.google.com/p/gearsinmotion/">Gears In Motion</a> which is very good.
</p>
<p>
If you desire to check the contents of localserver.db (the database for LocalServer) then it is suggested that you use a SQLite management client. A list of them can be found <a href="http://www.sqlite.org/cvstrac/wiki?p=ManagementTools">here</a>.
</p>
</dd>



<dt id="deteDatabases">
How do I delete databases that were created from the Gears API?
</dt>

<dd>
<p>
The Gears API does not provide a programmatic way to delete an existing database. Consider the following code, which creates a Gears Database:<br/>
<pre class="prettyprint">db = google.gears.factory.create('beta.database');
db.open('mydb');</pre>

</p>
<p>
Databases created with code such as this can only be explicitly removed from your local machine by physically deleting the corresponding database file generated for the browser. Gears Database files reside in the Gears data directory associated with the browser. The specific path to this directory depends on your browser and the underlying operating system. The Gears data directories for common configurations are listed in <a href='http://code.google.com/apis/gears/api_database.html#directories'>http://code.google.com/apis/gears/api_database.html#directories</a>.
</p>
<p>
The physical database file resides below the Gears data directory, according to this format: <br/>
<pre class="prettyprint">&#91;path&#93;/&#91;application url&#93;/http_&#91;port number&#93;/&#91;db name&#93;#database</pre>
</p>
</dd>



<dt id="prepareWorkerPoolCode">
How do I make JavaScript source code available to a child WorkerPool during initialization?
</dt>

<dd>
<p>
Since a Gears WorkerPool worker has no access to the address space of its parent worker, all source code must be explicitly passed in during child worker initialization as such -
</p>
<pre class="prettyprint">childCode = '......'; /* JavaScript code as string */
childId = workerPool.createWorker(childCode);</pre>

<p>
The challenge lies in creating a string that encapsulates all the JavaScript codes that will be required by the child worker, and there are three ways to do this:<br/>
<ol>
<li>
You can write out the entire code as a string to be passed in. For example:<br/>
<br/>
<pre class="prettyprint">childCode = 'function square(num) { return num*num; }';</pre>
</li>
<li>
You can wrap the code into a single function and use String() to flatten the function object into a string. For example:<br/>
<br/>
<pre class="prettyprint">function square(num) { return num * num; }
childCode = String(square);</pre>
</li>
<li>
You can retrieve it as a file string through an AJAX invocation (since local file reading is not allowed in JavaScript). For example:<br/>
<br/>
<pre class="prettyprint">/* XMLHttpRequestObject is the XHR object of your browser */
XMLHttpRequestObject.open("GET", 'square.js');
XMLHttpRequestObject.onreadystatechange = function() {
if (XMLHttpRequestObject.readyState == 4 &amp;&amp; XMLHttpRequestObject.status == 200) {
childCode = XMLHttpRequestObject.responseText;
}
}</pre>
</li>
</ol>
</p>
</dd>



<dt id="separatePorts">
If I have two applications on separate ports, will they have the same LocalServer and Database files?
</dt>

<dd>
<p>
No. Separate storages are made for separate domains. Gears looks at the protocol + host + port to determine domains. A different port would be a different domain.
</p>
</dd>



<dt id="crossOriginWorker">
What is a cross-origin worker? What is it useful for? How do I use it?
</dt>

<dd>
<p>
A cross-origin worker is WorkerPool worker created in a JavaScript file on a domain and has been initialized to run JavaScript code on a cross-origin server.
</p>
<p>
A cross-origin worker is useful because it is a secure solution to the cross-origin restriction policy of the browser. It allows you to make a request to a cross-origin server, even though the browser usually restricts this.
</p>
<p>
What can it be used for?
</p>
<ul>
<li>
Expose a service to users which was previously unreachable with an XMLHTTPRequest, due to cross-origin restrictions. By using cross-origin workers, you could make a web service API accessible to users' workers by putting a JavaScript worker file on your domain.
</li>
<li>
Offline resources that are on another domain. For instance, say you have a photo site and you have a separate server for the pictures. If you wanted to enable Gears offline support, you would have to do a <em>store.capture</em> on them which would fail due to cross-origin restrictions. However, if you had a JavaScript file on the other origin which called <em>store.capture</em>, then you could initiate a worker on that file and it would be successful.
</li>
</ul><br/>
<b>Example</b>
<p>
Take a cross-origin resource offline with a cross-origin worker.
</p>
<p>

----<em>cache_cross_origin_resource.html</em>----
</p>
<pre class="prettyprint">&lt;script type="text/javascript" src="gears_init.js"&gt;
&lt;/script&gt;&lt;script type="text/javascript"&gt;
// Create the workerpool
var workerPool = google.gears.factory.create('beta.workerpool');
// Set the message handler for when a worker sends a message
workerPool.onmessage = function(a, b, message) {
alert('Received message from worker ' + message.sender + ': ' + message.text);
};
// Create a worker from a JavaScript file on another origin
var childWorkerId = workerPool.createWorkerFromUrl('http://www.crossorigin.com/worker.js');
// Send a message to the worker. The worker's onmessage handler in worker.js will decide what to do with this
workerPool.sendMessage('crossOriginResource.html', childWorkerId);
&lt;/script&gt;</pre>
<p>
----<em>worker.js</em>----
</p>
<pre class="prettyprint">// Setup the WorkerPool
var wp = google.gears.workerPool;
// Allow a cross-origin script to run this
wp.allowCrossOrigin();
wp.onmessage = function(a,b,messageObject) {
// Ignore messages from unexpected origins
if(messageObject.origin == 'http://www.expectedorigin.com') {
// Create LocalServer
var localServer = google.gears.factory.create('beta.localserver');

// Create ResourceStore (Could also use ManagedResourceStore)
var store = localServer.createStore('Cross_Origin_Store');

// We are capturing the filename sent to us by the
// WorkerPool (crossOriginResource.html)
var fileToCapture = messageObject.text;

// Capture the file
store.capture(fileToCapture, function(url, success, captureId){
// When capture finishes, let the WorkerPool know the status
// This will cause workerPool.onmessage to alert the message received
wp.sendMessage(url + ' captured ' + (success ? 'succeeded' : 'failed'), messageObject.sender);
});
}
}</pre>
</dd>



<dt id="multipleWorkersAccessingDB">
Do I need to protect from multiple workers editing the database at once?
</dt>

<dd>
<p>
No. SQLite is thread-safe. However, if multiple workers attempt to access the database at once then some requests might fail. It is up to the application to have workers retry requests upon failure.
</p>
</dd>



<dt id="storeURLParameters">
Does LocalServer store URL parameters?
</dt>

<dd>

<p>
Yes. If you use a ResourceStore or a ManagedResourceStore and you store a URL with parameters then whatever was captured for that URL will be served back when that URL is requested.
Ex:
<pre class="prettyprint">store.capture('foobar.html?foo=1&bar=2');</pre>
When the browser requests <em>foobar.html?foo=1&bar=2</em> it will be served the stored page, but not when it requests <em>foobar.html</em>.
</p>
</dd>



<dt id="howToOfflineCrossOrigin">
How do I 'offline' a cross-origin resource?
</dt>

<dd>
<p>
First, read an article on the dangers of <a href="http://www.cgisecurity.com/articles/xss-faq.shtml">cross-origin scripting</a>.
</p>
<p>
After understanding the security risks, here are two potential solutions:<br/>
(1) Use Gears' cross-origin workers<br/>
(2) Use cross-origin proxying
</p>
<b>Solution (1)</b>
<p>
This is a safer alternative and therefore the suggested one. However, you must have access to put Javascript on any origins you wish to use. If you are trying to grab resources from an origin you do not control, use (2). However, be warned that this is unsafe and can expose you to attacks.
</p>
<p>
Say we have two origins, http://www.foo.com/ and http://www.bar.com/ with the style.css file on bar.com. What you do is create a WorkerPool on foo.com which does a createWorkerFromUrl. The URL it will create it from is a Javascript worker file that you have placed on bar.com.
</p>
<p>
The worker file on bar.com will then create a LocalServer and ResourceStore, then capture style.css.
</p>
<p>
Here is example code:<br/>
</p>
<i>test.hml (this origin is http://www.foo.com/)</i>
<pre class="code">&lt;script type="text/javascript" src="gears_init.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;
var workerPool = google.gears.factory.create('beta.workerpool', '1.1');
workerPool.onmessage = function(a, b, message) {
alert('Received message from worker ' + message.sender + ': ' + message.text);
};
var childWorkerId = workerPool.createWorkerFromUrl('http://www.bar.com/worker.js');
workerPool.sendMessage('', childWorkerId);
&lt;/script&gt;</pre>
<i>worker.js (this origin is http://www.bar.com/)</i>
<pre class="code">var wp = google.gears.workerPool;
wp.allowCrossOrigin();
wp.onmessage = function(a, b, message) {
localServer = google.gears.factory.create('beta.localserver', '1.1');
var store = localServer.createStore("Test_Store");
store.capture("style.css", function(){
wp.sendMessage("Captured!", message.sender);
});
}</pre>
For ease of reading, the try catch blocks that you should be using are left out! Don't forget them or to make sure the user has Gears installed.
<br/><br/>
<b>Solution (2)</b>
<p>
Be sure you understand the security risks of cross-origin proxying!
</p>
<p>
Use a PHP file that you store on the origin you are grabbing resources with to echo back the output of a resource from another origin. Then, to 'offline' this data, use resource store to store the PHP file with the exact parameters sent to it.
</p>
<p>
An example would be if I am on http://www.foo.com/ and I have a CSS located at http://www.bar.com/style.css. I would then tell my ResourceStore to pull down the URL http://www.foo.com/php_proxy.php?url=http://www.bar.com/style.css.php_proxy.php. The php_proxy would take the input url and do an HTTP request for that resource and echo it back as an image.
</p>
<p>
Here is what the code for php_proxy.php would look like:
</p>
<pre class="code">&lt;?php
header("Content-Type: text/css");
$base_url = $_GET['url'];

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $base_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_HEADER, false);

echo( curl_exec($ch) );
?&gt;</pre>
Then, in my HTML instead of:
<pre class="code">&lt;link rel="stylesheet" type="text/css" media="print" href="http://www.bar.com/style.css"/&gt;</pre>
I would use:
<pre class="code">&lt;link rel="stylesheet" type="text/css" media="print" href="http://www.foo.com/php_proxy.php?url=http://www.bar.com/style.css" /&gt;</pre>
The last step is to have the ResourceStore grab http://www.foo.com/php_proxy.php?url=http://www.bar.com/style.css
</dd>

<dt id="queryLocalServer">
Is there a tool to interactively manage and query Gears' LocalServer?
</dt>

<dd>
<style type="text/css">
/*table, table tr, table tr td { border:0; }*/#gc-pagecontent {border-left:3px solid #fff;}#breadcrumbs {padding:4px;}ul.section {list-style-type:none;line-height:155%;margin:0;padding:0 0 0 .2em}ul.section li {background-image: url(https://services.google.com/images/smallbullet.gif);background-repeat: no-repeat;background-position: 0 .6em;padding:0 0 0 .8em}.noticebox {border:1px solid #ccc;background: #efeff4;padding:6px;margin:8px 0 0 0;}</style>
<p>
If you've been wondering how to manage the stores and resources in Gears while developing, here's a solution. A script has been written which lets you add/remove stores, and the resources inside of them.
</p>
<p>
<strong>
Limitations:
</strong>
<ul>
<li>
Can only add/remove from domains the script is located on
</li>
<li>
Must add a symlink in your profile directory
</li>
</ul>
</p>
<p>
<strong>
(Mac/Linux) How to use it:
</strong>
<ol>
<li>
Navigate to your <a href="http://code.google.com/apis/gears/api_database.html#directories">Gears directory</a>.
</li>
<li>
Create a symlink:<br/>
<pre class="prettyprint">ln localserver.db &lt;<em>domain</em>&gt;/http_80/localserver#database</pre>
An example would be
<pre class="prettyprint">ln localserver.db www.google.com/http_80/localserver#database</pre>
</li>
<li>
Upload the <a href="http://code.google.com/articles/support/inspect_LocalServer_dbtail.html">LocalServer inspector</a> script to the domain you want to edit. Don't forget to put <a href="http://code.google.com/apis/gears/resources/gears_init.js">gears_init.js</a> there as well.
</li>
<li>
Navigate your browser to the location of the LocalServer inspector script.
</li>
</ol>
</p>
<p>
<p>
<strong>(Windows) How to use it:</strong>
<p>
There is no utility built in to Windows to create a hard link (the equivalent of Mac/Linux symlink). There is an <a href="http://shell-shocked.org/article.php?id=284">article</a> that talks about making hard links. A simple utility is Hard Link Magic.
</p>
<p>
Use a hard link utility to connect the <em>localserver.db</em> file located in your <a href="http://code.google.com/apis/gears/api_database.html#directories">Gears directory</a> to a new file, &lt;<em>gears directory</em>&gt;/&lt;<em>domain</em>&gt;/http_80/localserver#database.
</p>
<p>
Follow steps 3 &amp; 4 of the Mac/Linux section.
</p>

</p>
<strong>How it works:</strong>
<p>
The file <em>localserver.db</em>, located in your <a href="http://code.google.com/apis/gears/api_database.html#directories">Gears directory</a>, is an SQLite database file that keeps track of all stores and resources on all domains in your Gears LocalServer. To prevent different domains from editing each other's offline data, this file is protected from being accessed in Gears code.
</p>
<p>
By creating a symlink to that file in your domain, it is like putting the <em>localserver.db</em> file in that folder. The script then opens that database and queries it for the stores and databases.
</p>
</p>
<p>
<strong>
Troubleshooting:
</strong>
<p>
If you received the "File exists" error while trying to create the symlink or there is an error when you open the LocalServer inspector tool, then delete the file &lt;<em>GearsDirectory</em>&gt;/&lt;<em>domain</em>&gt;/http_80/localserver#database and recreate the symlink.
</p>

</p>

</dd>



<dt id="workerPoolDOMAccess">
Do WorkerPool workers have access to the DOM document object?
</dt>

<dd>

No, workers have no access to the DOM object. However, they can message back to their parent which can access the DOM. Also, two new modules were introduced in Gears versions 0.2+, HTTPRequest and Timer. These modules allow you to make HTTPRequests in workers, as well as use timers to execute timed events.
</dd>



<dt id="isOnlineFunction">
Is there an isOnline function in Gears to check whether the application is online? Do you plan to have one? Can you provide code for offline detection?
</dt>
<dd>

<p>
No, there isn't an isOnline function in Gears at this time. And currently, there are no plans to implement it.
</p>
<p>
There are 2 reasons why we haven't implemented it yet:
<ol>
<li>
There are multiple definitions of the application being 'offline'. The reason could be any of these:
<ul>
<li>
The browser has the 'work offline' flag set
</li>
<li>
The network cable is unplugged
</li>
<li>
The VPN is down
</li>
<li>
DNS is down
</li>
<li>
The server you are trying to reach is down
</li>
<li>
The server has a bug and cannot process your request
</li>
</ul>
We can't assume how an application should determine if it is offline or not because each application will have different requirements.
</li>
<li>
<p>
We don't want users to neglect syncing reliability.
</p>
<p>
The popular suggestion to implement isOnline has been to make a periodic XMLHttpRequest to a resource, whose success/failure would designate the application being on/offline. The problem with this is that you cannot assume that when a ping succeeds you can start syncing and be guaranteed that that you are online. For example, if isOnline() returns true and you start sending sync updates, something could happen in the connection between the user and the server and these syncs would be permanently lost - meanwhile the application still thinks it is online.
</p>
<p>
So instead what we encourage people to do is to queue all updates locally in the database module, and then try and send them to their server separately. If the update succeeds, remove them from the database. If the update fails for any reason, try again next time. In that way, you're always ready for the server to go down at any time and you never lose anything.
</p>

</li>
</ol>

</p>
<p>
<b>
Sample Code for periodic XMLHttpRequests
</b>
- uses Gears v0.2+ HTTPRequest
</p>
<p>
Here is some sample code that makes use of Gears' HTTPRequest module to change the UI of an application - let the user know when they are on/offline. It requires <em>gears_init.js</em> to be in the same directory.
</p>
<pre class="code">&lt;div id="serverStatus"&gt;&lt;/div&gt;
&lt;div id="pings"&gt;&lt;/div&gt;
&lt;script src="gears_init.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript" charset="utf-8"&gt;
var numPings = 0;
var request = google.gears.factory.create('beta.httprequest');
var TIME_BETWEEN_PINGS = 3*1000;
var PING_TIMEOUT_SECONDS = 1*1000;
function pingSuccess() {
if(request.responseText != "" &amp;&amp; request.responseText.indexOf("404 Page not found") == -1){
document.getElementById('serverStatus').innerHTML = "&#91;Server Accessible&#93;";
} else {
document.getElementById('serverStatus').innerHTML = "&#91;Server Inaccessible&#93;";
}
}

function isServerAvailable() {
var resource_to_test = "FAQs_to_write.txt";
resource_to_test += "?q=" + Math.floor(Math.random() * 100000);
request.open('GET', resource_to_test);
window.setTimeout("pingSuccess()",PING_TIMEOUT_SECONDS);
request.onreadystatechange = function() {
if (request.readyState == 4) {
numPings++;
document.getElementById('pings').innerHTML = "Number of pings: " + numPings;
}
};
request.send();
window.setTimeout("isServerAvailable()",TIME_BETWEEN_PINGS);
}
isServerAvailable();
&lt;/script&gt;</pre>
Be aware that the <em>resource_to_test</em> must be a file located on the same domain this code is running on. Also note that in the <em>pingSuccess</em> function, there is a test for a page returning "404 Page not found". Different domains will send the user a different 404 error, so please be aware of what check is correct for your domain.
<p>
<b>
Sample Code for browser being offline
</b>

</p>
<p>
To check if the user has manually told the browser to work offline, use this:
</p>
<pre class="code">alert(navigator.onLine);</pre>
<p>
Note: This works on IE and Firefox
</p>
</dd>



<dt id="automaticOffline">
Does Gears automatically make my web application work offline?
</dt>

<dd>
<p>
Gears extends browsers by making new APIs available to JavaScript code. Like all APIs, they must be used explicitly. To take advantage of the offline features provided by Gears, you'll need to add or change code in your web application.
</p>
<br />
<p>
There are three core modules provided by Gears: a <a href="http://code.google.com/apis/gears/api_localserver.html">LocalServer</a> for storing and accessing application pages offline, a <a href="http://code.google.com/apis/gears/api_database.html">Database</a> for storing and accessing application data on the user's computer, and a <a href="http://code.google.com/apis/gears/api_workerpool.html">WorkerPool</a> for performing long-running tasks (such as the code that synchronizes data between your server and users' computers). For more information, follow the links.
</p>
<br />
<p>
A <a href="http://code.google.com/apis/gears/tutorial.html">Gears Tutorial</a> is available that illustrates the basic concepts. You may also find the <a href="http://code.google.com/apis/gears/sample.html">Gears sample applications</a> useful. Source code for these samples can be downloaded in a zip file found on the same page.
</p>
</dd>



<dt id="howMakeOffline">
Gears lets my web application work offline, right? How do I do that?
</dt>

<dd>
<p>
Gears provides a LocalServer module to access application data offline. This module consists of two sub-parts:
</p>
<ul>
<li>
A ResourceStore, used to capture application content (such as images and static files) for later use offline
</li>
<li>
A ManagedResourceStore, used to capture the URLs that make up an application
</li>
</ul>
<p>
More information is available in the <a href="http://code.google.com/apis/gears/api_localserver.html" title="LocalServer API documentation">LocalServer API documentation</a>.
</p>
</dd>



<dt id="howStoreData">
Gears lets my web application store data on the user's computer, right? How do I do that?
</dt>

<dd>
<p>
Gears provides a Database module to store and retrieve data from a user's computer. This module consists of a SQL interface to a relational database embedded in the user's browser as part of Gears. Tables can be created to store data, in a manner that will be familiar to any SQL developer.
</p>
<br/>
<p>
More information is available in the <a href="http://code.google.com/apis/gears/api_database.html" title="Database API Documentation">Database API Documentation</a>.
</p>
</dd>



<dt id="howRunBackground">
Gears lets my web application run code in the background, right? How do I do that?
</dt>

<dd>
<p>
Gears provides a WorkerPool module to run JavaScript code in separate contexts. These contexts (which are similar to threads) run in isolated JavaScript environments, and have no window object, document object, or other DOM elements. However, these threads do have access to the XmlHttpRequest function, and so can make AJAX-style calls as necessary. This is frequently useful to implement a component that synchronizes data between a user's computer (for offline use) and the server (for online use and backup).
</p>
<br/>
<p>
Workers from the same pool can communicate with each other by passing messages.
</p>
<br/>
<p>
More information is available in the <a href="http://code.google.com/apis/gears/api_workerpool.html" title="WorkerPool API Documentation">WorkerPool API Documentation</a>.
</p>
</dd>



<dt id="linuxCompatible">
What does Gears require to be compatible with my Linux system?
</dt>

<dd>
If you'd like to run the Gears for Firefox on a Linux (32-bit) platform, please make sure your system has glibc 2.3.5 or higher and libstdc++6 (Gears 0.3) or libstdc++5 (Gears pre-0.3).
</dd>



<dt id="whereAreFiles">
Where are Gears files stored?
</dt>

<dd>
<p>
<strong>
Windows Vista - Internet Explorer
</strong>

</p>
<p>
Location: {FOLDERID_LocalAppDataLow}\Google\Gears for Internet Explorer<br />
Example: C:\Users\Bob\AppData\LocalLow\Google\Gears for Internet Explorer
</p>
<p>
<strong>
Windows Vista - Firefox
</strong>
- Files are stored in the user local profile directory.
</p>
<p>
Location: C:\Users\&lt;username&gt;\AppData\Local\Mozilla\Firefox\Profiles\{profile}.default\Gears for Firefox <br />
Example: C:\Users\Bob\AppData\Local\Mozilla\Firefox\Profiles\uelib44s.default\Gears for Firefox
</p>
<p>
<strong>
Windows XP - Internet Explorer
</strong>
- Files are stored in the user local profile directory.
</p>
<p>
Location: C:\Documents and Settings\&lt;username&gt;\Local Settings\Application Data\Google\Gears for Internet Explorer<br />
Example: C:\Documents and Settings\Bob\Local Settings\Application Data\Google\Gears for Internet Explorer
</p>
<p>
<strong>
Windows XP - Firefox
</strong>
- Files are stored in the user local profile directory.
</p>
<p>
Location: C:\Documents and Settings\&lt;username&gt;\Local Settings\Application Data\Mozilla\Firefox\Profiles\{profile}\Gears for Firefox<br />
Example: C:\Documents and Settings\Bob\Local Settings\Application Data\Mozilla\Firefox\Profiles\uelib44s.default\Gears for Firefox
</p>
<p>
<strong>
Mac OS X - Firefox
</strong>
- Files are stored in the user local profile directory.
</p>
<p>
Location: Users/&lt;username&gt;/Library/Caches/Firefox/Profiles/{profile}.default/Gears for Firefox <br />
Example: Users/Bob/Library/Caches/Firefox/Profiles/08ywpi3q.default/Gears for Firefox
</p>
<p>
<strong>
Linux - Firefox
</strong>
- Files are stored in the user home directory.
</p>
<p>
Location: ~<em>bob</em>/.mozilla/firefox/&lt;firefox's profile id&gt;/Gears for Firefox <br />
Example: ~bob/.mozilla/firefox/08ywpi3q.default/Gears for Firefox
</p>
<p>
<strong>
Microsoft Windows Mobile - Internet Explorer
</strong>
- Files are stored in the Application Data directory.
</p>
<p>
Location: \Application Data\Google\Gears for Internet Explorer
</p><br/>
<b>What do the files do?</b>
<p>
<strong>
localserver.db
</strong>
- This is a SQLite database that keeps track of all files that are stored in the LocalServer across all domains. This file is used in the internals of the Gears code, and cannot be accessed from within a Gears program.
</p>
<p>
<strong>
permissions.db
</strong>
- This is a SQLite database that keeps track of all domains that have been allowed to use Gears.
</p>
<p>
<strong>
&lt;<em>domain</em>&gt;/http_80/&lt;<em>filename</em>&gt;#database
</strong>
- This is a SQLite database file that has been created by an application on &lt;<em>domain</em>&gt;
</p>
<p>
<strong>
&lt;<em>domain</em>&gt;/http_80/&lt;<em>filename</em>&gt;#localserver
</strong>
- This is a folder that contains files cached by either type of LocalServer store, a ResourceStore or a ManagedResourceStore, created by &lt;<em>domain</em>
&gt;
</p>
</dd>

<hr>

<h2 id="Best__Practices">Best Practices</h2>

<dt id="bestPracticeStartGears">
Best Practices for Starting With Gears
</dt>

<dd>
<p>
Most developers jump into Gears and want to take their application offline immediately. Creating offline web applications is hard. Instead, we suggest you start slowly and use other Gears features first, identifying easier projects that can get running code quickly and get you familiar with the <a href="http://code.google.com/apis/gears/">Gears API</a>. The following are some suggested ways to get your feet wet with Gears from easiest to hardest:
</p>

<p id="startGearsSpeedUp">
<em>Speed Up Static Resources</em>
</p>

<p>
The best first place to start is to use Gears to speed up your web application using the <a href="http://code.google.com/apis/gears/api_localserver.html">LocalServer</a> module. <a href="http://www.wordpress.com">WordPress</a>, a popular blogging platform, <a href="http://en.blog.wordpress.com/2008/07/02/gears/">uses Gears and the LocalServer module</a> to significantly improve the performance of common operations. WordPress incorporates a rich text editor that makes authoring posts much easier. However, this editor has a ton of associated resources, such as CSS, JavaScript, images, etc. (more than a hundred!). Downloading these resources, including seeing if they have changed using traditional HTTP caching, can affect the performance of using the editor, especially on latent connections.
</p>

<p>
Instead, WordPress decided to download all of these resources into a Gears LocalServer. The Gears LocalServer makes it possible to version a bundle of resources, such as JavaScript, CSS, etc. and grab them in one shot. Once files have been stored in the Gears LocalServer they are served up locally and immediately, blitting to the screen right when the page is first hit.
</p>

<p>
A common question is how this is different than standard HTTP caching. Standard HTTP caching can only version individual resources, and must do validity checks on every resource at regular intervals which can affect page load time. The Gears LocalServer instead versions an entire bundle, efficiently checking that resources have changed only if the version on the bundle itself has changed. Another major difference is that Gears always serves the resources first, then revalidates the bundle. In traditional HTTP caching, you have to either choose between choosing some date far in the future to revalidate at, or revalidating before serving.
</p>

<p id="startGearsDataCache">
<em>Cache Data and Use Search Locally</em>
</p>

<p>
A great next step is to use the Gears' <a href="http://code.google.com/apis/gears/api_database.html#sqlite_fts">Full Text Search</a> capabilities to give your users very fast local search. This can be used in conjunction with the Gears <a href="http://code.google.com/apis/gears/api_database.html">Database</a> module to cache commonly used data for faster display and retrieval.
</p>

<p>
<a href="http://www.myspace.com">MySpace</a> <a href="http://gearsblog.blogspot.com/2008/05/myspace-message-center-is-now-searching.html">does this with their MySpace Mail feature</a>. They download all of a users messages in the background using a Gears <a href="http://code.google.com/apis/gears/api_workerpool.html">WorkerPool</a>, index them into the Database for quick retrieval, and then drop a search form on to the page. As a user types the local database is queried in real-time, with the results shown instantaneously on the page without the latency of a round-trip server call.
</p>

<p>
You can also use the local database to cache commonly used data, such as zip code lookup tables or employee contact information. For example, MySpace uses this to provide fast, client-side sorts. A user can click the sort icon while viewing messages to sort by read/unread, date sent, sender, etc. Rather than having to return to the server, affecting performance, the sort happens very fast on the client-side using SQL against the local database.
</p>

<p>
For an example with source code you can use of caching commonly used data locally <a href="http://google-ajax-examples.googlecode.com/svn/trunk/presidentialwithgears/election2008.html">see here</a>.
</p>

<p id="startGearsGoingOffline">
<em>Going Offline</em>
</p>

<p>
Going offline can be a great step once you have familiarized yourself with Gears. See <a href="#offlineArchitectures">Best Practices for Offline Architectures</a> for details on how to begin.
</p>

<p>For more creative ways to use Gears here are some suggested uses for the various Gears modules:</p>

<p id="goodUsesForLS">
<em>Good Uses for LocalServer</em>
</p>

<ul>
<li>
Caching all application resources for faster performance or offline
experience
</li>
<li>
Enabling <a href="http://code.google.com/apis/gears/api_localserver.html#FileSubmitter">"offline uploads"</a>
</li>
<li>
Caching media files
</li>
</ul>

<p id="goodUsesForDB">
<em>Good Uses for Database</em>
</p>

<ul>
<li>Caching previous internet queries</li>
<li>
Locally storing copies of remote databases for faster performance
</li>
</ul>

<p id="goodUsesForWP">
<em>Good Uses for WorkerPool</em>
</p>

<ul>
<li>Running complex computations in the background, so as not to affect UI</li>
<li>Allowing <a href="#crossOriginWorker">cross-domain Ajax requests</a></li>
<li>Doing all database interaction in the background</li>
<li>Keeping data syncing in the background</li>
</ul>
</dd>

<dt id="offlineArchitectures">
Best Practices for Offline Architectures
</dt>

<dd>
<p>
If you've decided that taking your web application offline is appropriate (see <a href="#bestPracticeStartGears">Best Practices for Starting With Gears</a> first), you need to decide on the architecture you will use.
<p>

<p>
You must first start by deciding what to take offline. We recommend starting small. Instead of taking everything offline, identify one or two key features that your users would find particularly useful while away from the network. For example, for a blogging tool, writing posts offline is very useful, while being able to change your site's administrative settings while offline is probably not.
</p>

<p>
The degree to which your web application is divided between the client and server will affect how easily you can take your application offline. In short, the more state and behavior you have on the client the easier it will be to take offline. For example, <a href="http://www.rememberthemilk.com">Remember the Milk</a> was able to <a href="http://gearsblog.blogspot.com/2007/09/gears-case-study-what-we-learned-from.html">take their application offline in a few days</a> because it is almost entirely a thick client, Ajax application, calling exposed APIs on the server-side. An application that has almost all the logic on the server-side, however, generating 'dumb' HTML sent to the client will be much more difficult to take offline. In this case, it will be difficult in that the generation of that HTML will have to be replicated on the client when the server is unavailable.
</p>

<p>
Next, you must decide how to do syncing. When it comes to syncing we recommend choosing your battles. The syncing problem is actually a continuum from easiest to most challenging. The easiest is to treat your local data as a read-only cache that you throw-away on each sync. The hardest is to treat offline data as both read and write that is potentially manipulated by multiple users, with automatic merging and conflict detection. The 'dumber' you can make your offline cache more towards single-user, read-only, the easier syncing will be. See <a href="#syncing">Best Practices for Syncing</a> for a more detailed discussion on this topic.
</p>

<p>
Further, you need to handle how to do on- and off-line detection. See <a href="#offlineDetection">Best Practices for Online/Offline Detection</a> for more details.
</p>

<p>
Finally, you need to architect your actual application. See <a href="http://code.google.com/apis/gears/architecture.html">this tutorial</a> for a full discussion on disconnected architectures. Another great resource is <a href="http://code.google.com/support/bin/answer.py?answer=73848&topic=11982">Taking Web Applications Offline with Google Gears</a> written by Omar Kilani from <a href="http://www.rememberthemilk.com">Remember the Milk</a>.
</p>
</dd>

<dt id="offlineDetection">
Best Practices for Online/Offline Detection
</dt>

<dd>
<p>
Online and offline detection is necessary for creating offline web applications. Two possibilities exist. Either the user manually moves into and out of offline mode through your user interface, or you automatically detect when the network appears and disappears and shift into offline mode seamlessly. We recommend starting small and doing the manual mode first. Automatic network detection is trickier than expected at first glance. While this puts a burden on the user, it can significantly simplify your code and reduce bugs. Seamless detection is a great goal to target once you have manual toggling down. Google Reader, for example, requires the user to manually click an icon to sync and download posts, and another click to move on- and off-line. Even if you have automatic network detection, you should provide a way for the user to manually attempt to go back online if they are offline. See <a href="#isOnlineFunction">this FAQ entry</a> for source code for automatic online/offline detection.
</p>
</dd>

<dt id="bestGearsPerms">
Best Practices for Gears Permissioning
</dt>

<dd>
<p>
A bad practice is to immediately show the Gears permission dialog when a first page loads. This will annoy users.
</p>

<p>
Instead, we recommend having the permission dialog appear based on a user-initiated action rather than automatically. For example, in WordPress, <a href="http://en.blog.wordpress.com/2008/07/02/gears/">which uses Gears to speed up loading the blogging rich text editor</a>, a small link appears next to the editor that says "Turbo". When the user presses this link, the Gears dialog prompt appears asking the user for permission to use the <a href="http://code.google.com/apis/gears/api_localserver.html">LocalServer</a>.
</p>

<p>
The Gears permission prompt appears automatically whenever you call the <a href="http://code.google.com/apis/gears/api_factory.html">Factory APIs</a> <code>google.gears.factory.create</code> method and permission has not been granted before. Avoid calling this method during page load, and only when the user has indicated they would like to use Gears by clicking on a link or button.
</p>

<p>
A related practice is to inform the user on why they should enable Gears. Rather than popping up the standard Gears dialog with no explanation on the feature, you should provide some explanatory text on what Gears will do for the user and provide an icon by using <code>google.gears.factory.hasPermission</code> and then showing the dialog using <code>google.gears.factory.getPermission()</code>:
</p>

<pre class="prettyprint">
if (!google.gears.factory.hasPermission) {
var siteName = 'My Site';
var icon = 'images/myIcon.png';
var msg = 'This site would like to use Google Gears to enable fast, '
+ 'as-you-type searching of its documents.';

var allowed = google.gears.factory.getPermission(siteName, icon, msg);
}
</pre>

<p>
More information on <code>hasPermission</code> and <code>getPermission</code> are available in the <a href="http://code.google.com/apis/gears/api_factory.html">Factory API documentation</a>.
</p>
</dd>

<dt id="detectingGears">
Best Practices for Installation and Detection
</dt>

<dd>
<p>
Before using Gears, you should first detect to see if the <code>google.gears</code> object is present and available:
</p>

<pre class="prettyprint">
if (!window.google || !window.google.gears) {
// Gears not installed
}
</pre>

<p>
If Gears is not present, you should display a link that when pressed will allow the user to install Gears. The Gears installation page can be customized to include your own text and message, as well as the ability to force the browser to re-navigate to your web application if the browser needed a restart:
</p>

<pre class="prettyprint">
if (!window.google || !window.google.gears) {
var message = 'To enable fast client-side search of this website '
+ 'please install Gears';
var url = 'http://gears.google.com/?action=install'
+ '&amp;message=' + encodeURIComponent(message)
+ '&amp;return=' + encodeURIComponent(window.location.href);
widget.innerHTML = '&lt;a href="' + url + '"&gt;Install '
+ 'Gears to enable fast search!&lt;/a&gt;';
return false;
</pre>

<p>
When using the <code>message</code> and <code>return</code> arguments on the Gears installation URL, always make sure the encode the argument values using JavaScript's <code>encodeURIComponent</code> method as in the example code above.
</p>

<p>
Finally, Gears is an open source project and we highly encourage contribution. However, we must discourage hosting your own versions of Gears because the auto-updating mechanism will not work properly. It is best for users if Gears provides a consistent user experience and can push any critical updates to all installs.
</p>

<p>
See <a href="http://code.google.com/apis/gears/design.html#detecting">Nuts and Bolts: Detecting and Installing Gears</a> for more information.
</p>
</dd>

<dt id="cachingDifferentDomain">
Best Practices for Using LocalServer With Web Applications Spread Across Different Hosts
</dt>

<dd>
<p>
A common pattern many web sites use is to partition static content onto a separate domain, such as static.example.com, away from the main dynamic content of a web site, such as example.com. This can make working with the <a href="http://code.google.com/apis/gears/api_localserver.html">LocalServer</a> difficult, as the LocalServer can only download resources that come from the same domain, in this case example.com.
</p>

<p>
The current way to solve this is to use <a href="#crossOriginWorker">Cross-Origin Workers</a> in conjuction with the LocalServer.
</p>

<p>
First, create a file that is hosted on your static domain; in our example this would be hosted on <code>static.example.com</code> and named <code>cache-worker.js</code>. We will also have a manifest file named <code>manifest.js</code> hosted on <code>static.example.com</code> with the list of URLs to capture. The URLs in <code>manifest.js</code> will all load relative to <code>static.example.com</code>:
</p>

<p>
----<em>static.example.com/manifest.js</em>----
</p>

<pre class="prettyprint">
{
"betaManifestVersion": 1,
"version": "1",
"entries": [
{ "url": "image1.png" },
{ "url": "image2.png" },
{ "url": "image3.png" },
{ "url": "myCSS.css" }
]
}
</pre>

<p>
----<em>static.example.com/cache-worker.js</em>----
</p>

<pre class="prettyprint">
// Setup the WorkerPool
var wp = google.gears.workerPool;

// Allow a cross-origin script to run this
wp.allowCrossOrigin();

wp.onmessage = function(a, b, messageObject) {
// Ignore messages from unexpected origins
if (messageObject.origin == 'http://example.com'
&amp;&amp; messageObject.text == 'Download Files') {
// Create LocalServer
var localServer = google.gears.factory.create('beta.localserver');

// Create our ManagedResourceStore
var store = localServer.openManagedStore('Cross_Origin_Store')
|| localServer.createManagedStore('Cross_Origin_Store');

store.manifestUrl = 'manifest.js';
store.checkForUpdate();

// if you want to get more advanced, you could setup LocalServer
// event handlers (onprogress, oncomplete, onerror) to track status
// of capture and send the results back as you receive them to the
// worker that called you
}
}
</pre>

<p>
We now have a cross-origin worker on <code>static.example.com</code> that we can 'message' and direct it to download its static resources into a LocalServer. Since the LocalServer is run inside of the worker on <code>static.example.com</code> it can download resources from that domain.
</p>

<p>
The last piece to tie together our code is to have the primary domain, in our example <code>example.com</code>, send a message to the worker on <code>static.example.com</code> when we are ready to capture resources into the LocalServer:
</p>

<p>
----<em>example.com/cache_cross_origin_resource.html</em>----
</p>

<pre class="prettyprint">
&lt;script type="text/javascript" src="gears_init.js"&gt;
&lt;/script&gt;&lt;script type="text/javascript"&gt;
// Create the workerpool

var workerPool = google.gears.factory.create('beta.workerpool');

// Create a worker from a JavaScript file on another origin
var childWorkerId = workerPool.createWorkerFromUrl('http://static.example.com/cache-worker.js');

// Tell worker to start downloading files into the LocalServer
workerPool.sendMessage('Download Files', childWorkerId);
&lt;/script&gt;
</pre>

<p>
For more discussion on this topic see <a
href="#howToOfflineCrossOrigin">How do I 'offline' a cross-origin
resource?</a> and <a href="#crossOriginWorker">What is a cross-origin worker? What is it useful for? How do I use it?</a>.
</p>

</dd>

<dt id="bestPracticeDB">
Best Practices for Database Performance and Reliability
</dt>

<dd>
<p>
This section provides several tips for improving the performance and reliability when working with the Gears <a href="http://code.google.com/apis/gears/api_database.html">Database</a>.
</p>

<p>
To increase performance:
</p>

<p>
First, if you are doing anything more than basic reading and writing to the database, you can dramatically improve the user-experience and performance by ensuring that all reads and writes happen from a Gears <a href="http://code.google.com/apis/gears/api_workerpool.html">Worker</a>, rather than on the browser's UI thread. For example, indexing a document or data into the Gears database for full-text search is much better done on a Worker than on the browser thread, which will keep the browser responsive:
</p>

<pre class="prettyprint">
var pool = google.gears.factory.create('beta.workerpool');

// a message handler that will be called when worker is done
pool.onmessage = function(message) {
alert('Finished indexing: ' + message);
}

// the code to run on the worker
function indexDocument(a, b, messageObj) {
// get arguments passed in
var args = messageObj.body;

// open the database -- we pass in the database name when
// messaging the worker
var db = google.gears.factory.create('beta.database');
db.open(args.dbName);

// add a new row to our full-text search table
try {
db.execute('INSERT INTO ClientSearch '
+ '(url, title, mimeType, content) '
+ 'VALUES (?, ?, ?, ?)',
[args.url, args.title, args.mimeType, args.doc]);
} finally {
db.close();
}

google.gears.workerPool.sendMessage(args.url, message.sender);
}

// create worker
var workerScript = 'google.gears.workerPool.onmessage = '
+ String(indexWorker);
var workerID = pool.createWorker(workerScript);

// have worker run time-consuming database operations
var msg = {url: 'somedoc.txt', title: 'Some Title',
mimeType: 'text/plain', doc: 'A short document',
dbName: 'mydatabase'};
pool.sendMessage(msg, workerID);
</pre>

<p>
If you were to run the above code on the main browser's thread rather than a Worker over and over your users' browsers would grind to a halt. With a Gears Worker the browser will remain responsive and usable, with overall performance faster.
</p>

<p>
Second, if you are doing several operations at once, surrounding them with an explicit transaction will increase performance; if you don't, every call to <code>execute</code> on the Database object will have an implicit transaction, slowing things down in tight loops or when dealing with several database operations:
</p>

<pre class="prettyprint">
var db = google.gears.factory.create('beta.database');
db.open('my_database');

db.execute('BEGIN');

try {
// do lots of db.executes() here
db.execute('COMMIT');
} catch(exp) {
db.execute('ROLLBACK');
} finally {
db.close();
}
</pre>

<p>
For more information on the SQL to setup transaction see <a href="http://www.sqlite.org/lang_transaction.html">this page.</a>
</p>

<p>
Third, the more you depend on SQL <a href="http://www.sqlite.org/lang_insert.html">INSERTs</a> rather than <a href="http://www.sqlite.org/lang_update.html">UPDATEs</a> to write data into a table the faster things will be. For example, imagine you have a network process that is slowly trickling down the information you need to add a new row to your table. You could do a single INSERT at the beginning of the process, and then run a series of UPDATEs as each new column of information comes in. However, if you simply cache this data in memory and then do one INSERT when all the data is available the Gears embedded database will perform better.
</p>

<p>
To ensure reliability:
</p>

<p>
First, make sure you always close <em>both</em> your database <em>and</em> your <code>ResultSets</code>. Both database connections and ResultSets are handles to OS-level resources that should be closed when finished. The best way to do this is to have a <code>finally</code> block that will get run whether an exception occurs or not:
</p>

<pre class="prettyprint">
var db = google.gears.factory.create('beta.database');

try {
db.open('database-test');
db.execute('create table if not exists Test' +
' (Phrase text, Timestamp int)');
db.execute('insert into Test values (?, ?)', ['Monkey!', new Date().getTime()]);
var rs = db.execute('select * from Test order by Timestamp desc');

while (rs.isValidRow()) {
alert(rs.field(0) + '@' + rs.field(1));
rs.next();
}
} finally {
if (rs) {
rs.close();
}
db.close();
}
</pre>

<p>
The second way to increase database reliability only applies if you reading or writing from the database from Workers. If you have multiple Workers or have code where both the browser and a Worker are working with the same database, you can sometimes get "Database Locked" exceptions. The best way to mitigate this is to centralize all of your database code on to a single Worker rather than have it scattered across multiple Workers or browser-code that could potentially run at the same time. A good pattern is to use a switch statement inside your worker, passing in the action to run, working with the database inside each function:
</p>

<pre class="prettyprint">
// worker.js
var wp = google.gears.workerPool;

wp.onmessage = function(a, b, message) {
var action = message.body.action;
switch (action):
case 'download':
download();
break;
case 'index':
index();
break;
case 'search':
search();
break;
}
}

function download() {
// code to download data on a worker here and store its metadata into
// the database
}

function index() {
// code to take a document and index it into the database here
}

function search() {
// code to search for a document in the database here
}
</pre>

<pre class="prettyprint">
&lt;script type="text/javascript"&gt;
// main.js
var workerPool = google.gears.factory.create('beta.workerpool');
var childWorkerId = workerPool.createWorkerFromUrl('worker.js');

workerPool.sendMessage({action: 'download'}, childWorkerId);
&lt;/script&gt;
</pre>

</dd>

<dt id="offlineUI">
Best Practices for Offline User Interfaces
</dt>

<dd>
<p>
Web applications that work offline should have the following elements:
</p>

<ul>
<li>Online/offline indicator - This can either switch automatically or be toggled manually by the user to move on- or off-line. See Best Practices for Online/Offline Detection for details.</li>
<li>Sync button and feedback - A button to initiate syncing (might possibly happen automatically when the network reappears) and suitable feedback to the user during the syncing process so they know activity is occuring.</li>
<li>Offline settings - A way to configure your offline application. This should include the ability to manually disable offline ability if the user does not wish to use this feature anymore. It should also include the ability to manually create a new desktop shortcut if you are using this feature (see Best Practices for Desktop Shortcuts).</li>
<li>Disabled elements - Portions of your user interface that do not work offline, such as searching, should be disabled.</li>
</ul>

<p>
In general, your web application should allow the user to manually turn on offline ability with a small link in your application's toolbar, such as the word "Offline". Here is a screenshot from Google Docs:
</p>

<p>
<img src="resources/google_docs_offline1.png" />
</p>

<p>
When pressed, you should show a permission dialog informing the user about using your application offline and asking for Gears permission; see <a href="#bestGearsPerms">Best Practices for Gears Permissioning</a> for more information on customizing the Gears permission dialog. It is important that users not try to setup an offline application on a shared, public computer, such as in an Internet cafe. See <a href="#storingData">Best Practices for Storing Data on Users' Machines</a> for more information on this. Here is the modal permission dialog that <a href="http://docs.google.com">Google Docs</a> shows:
</p>

<p>
<img src="resources/google_docs_offline2.png" />
</p>

<p>
Once setup, you should indicate to the user three modes: online, offline, and syncing. During syncing, you should provide a short message for the user informing them on syncing status. A screenshot from Google Docs:
</p>

<p>
<img src="resources/google_docs_offline3.png" />
</p>

<p>
When online and synced, you should display a small icon. A screenshot from Google Docs:
</p>

<p>
<img src="resources/google_docs_offline4.png" />
</p>

<p>
Since users might wonder what this icon is, it is good to provide a small label that appears when the user mouses over, such as "Online. Click for Details." When clicked Google Docs shows the following:
</p>

<p>
<img src="resources/google_docs_offline5.png" />
</p>

<p>
You should also show an icon when offline with a label when the mouse is run over it. Google Docs shows the following for the icon:
</p>

<p>
<img src="resources/google_docs_offline6.png" />
</p>

<p>
When you run the mouse over this icon, a label appears that says "Offline. No Connection is Available." When the icon is pressed, you should provide the user with some context and a way to manually try to reconnect:
</p>

<p>
<img src="resources/google_docs_offline7.png" />
</p>

<p>
The decision on whether to make online and offline detection manual or automatic is up to you; see <a href="#offlineDetection">Best Practices for Online/Offline Detection</a> for a discussion on this topic.
</p>

<p>
You should also provide a settings dialog where the user can turn the offline feature off and create a new desktop shortcut icon if you are using the Gears <a href="http://code.google.com/apis/gears/api_desktop.html">Desktop API</a>. Here is a screenshot of Google Docs offline settings pane:
</p>

<p>
<img src="resources/google_docs_offline8.png" />
</p>

<p>
As always, its good to provide short help text on what Gears is to the user so they can learn more about how your application is using their local machine in Gears. Clicking the Learn More link in the above screenshot leads to the following help text for Google Docs:
</p>

<p>
<img src="resources/google_docs_offline9.png" />
</p>

<p>
As a final note, make the offline experience match the online as much as possible, and use a consistent UI convention for disabling functionality. With Google Docs, we don't have an "offline editor" we have an offline mode. When offline, certain features necessarily won't work. But rather than hiding them or replacing them with a distinct UI, we simply gray them out. That provides another clue to the user that they are in offline mode while retaining the familiarity of the application.
</p>
</dd>

<dt id="maintainWorkers">
Best Practices for Maintainable Workers
</dt>

<dd>
<p>
As your Gears-based projects get more sophisticated keeping your <a href="http://code.google.com/apis/gears/api_workerpool.html">Worker</a> code organized and maintainable can get tricky. Here are several tips and best practices for keeping things organized.
</p>

<p>
First, you can use the WorkerPool <code><a href="http://code.google.com/apis/gears/api_workerpool.html#createworkerfromurl">createWorkerFromUrl</a></code> method to partition all of your worker script into a single file, which you can then instantiate to run on the worker.
</p>

<p>
If you'd like to keep your primary application code and workers in the same file, however, you can 'stringify' specific methods and send them into the worker. It is also good practice to encapsulate external code from the fact that workers are being used; application code should simply be able to call a JavaScript class with data to be worked on and a callback, without being exposed to the Worker-specific implementation.
</p>

<p>
Here is an example snippet of code where we have a Worker that will index a set of documents on a Worker into a full-text table in the Gears relational database. We encapsulate external callers of this code from this fact by creating creating a JavaScript 'class' named <code>Indexer</code> that can be called with an array of documents to index and a callback function when finished. Here's pseudo-code for the Indexer:
</p>

<pre class="prettyprint">
// constructor
function Indexer(docs, callback) {
this.docs = docs;
this.callback = callback;

this.run_(); // kick off worker
}

Indexer.prototype.run_: function() {
// the code to run on the worker
var workerScript = 'var supportFunction_ = '
+ String(this.supportFunction_) + '; '
+ 'google.gears.workerPool.onmessage = '
+ String(this.indexWorker_);

// the message handler that gets return results from the worker
var worker = google.gears.factory.create('beta.workerpool');
worker.onmessage = pu.hitch(this, function(a, b, message) {
if (message.text == 'finished') {
callback(); // we are done
}
});

// send the worker a message to run
var childWorkerId = worker.createWorker(workerScript);
worker.sendMessage(docs, childWorkerId);
}

Indexer.prototype.indexWorker_: function() {
// the code that would run on the index worker goes here
}

Indexer.prototype.supportFunction_: function() {
// some support function needed inside the worker goes here
}

// callers using the call are encapsulated:
var idx = new Index(myDocs, myCallback);
</pre>

<p>
A few things to notice about the code above. First, we use JavaScript class notation to encapsulate our methods together. Second, we 'stringify' some of the methods inside of the class to pass into the worker using the <code>String()</code> method in JavaScript:
</p>

<pre class="prettyprint">
// the code to run on the worker
var workerScript = 'var supportFunction_ = '
+ String(this.supportFunction_) + '; '
+ 'google.gears.workerPool.onmessage = '
+ String(this.indexWorker_);
</pre>

<p>
Calling <code>String()</code> on a function will simply output a stringified version of that function. For example, calling <code>String(this.supportFunction_)</code> outputs the following:
</p>

<pre class="prettyprint">
function() {
// some support function needed inside the worker goes here
}
</pre>

<p>
Notice that no function name is output; this is why we have to capture the stringified version into a variable when passing it into the worker:
</p>

<pre class="prettyprint">
var workerScript = 'var supportFunction_ = '
+ String(this.supportFunction_)
</pre>

<p>
The <code>google.gears.workerPool.onmessage</code> assignment gives the WorkerPool <code>onmessage</code> method that will execute when the worker is sent a message. In our example code above, we make sure that the <code>indexWorker_</code> function will get run. You could have as many helper functions as necessary for this Worker to call by using the <code>String()</code> trick above. The code above makes it easy to encapsulate your Worker code into easy to call classes to keep your application bundled into a single JavaScript file.
</p>
</dd>

<dt id="choosingNames">
Best Practices for Choosing Names for Databases and LocalServers
</dt>

<dd>
<p>
When you open or create a Gears <a href="http://code.google.com/apis/gears/api_database.html">Database</a> or <a href="http://code.google.com/apis/gears/api_localserver.html">LocalServer</a>, you must give them a name:
</p>

<pre class="prettyprint">
// LocalServer
var localServer = google.gears.factory.create('beta.localserver');
var store = localServer.createManagedStore('test-store');

// Database
var db = google.gears.factory.create('beta.database');
db.open('test-database');
</pre>

<p>
We recommend that you don't just choose a static string such as the <code>test-store</code> name given above for several reasons:
</p>

<ul>
<li>If you have several Gears applications on the same domain and they use the same string, your Databases and LocalServers can possibly collide creating hard to track down bugs.</li>
<li>Even if you only have one Gears-based application hosted at your domain, if several users share the same OS-level account their data can get confused. For example, imagine you open a Database with the name <code>my-database</code> and store Bobs settings in there. Alice shares this computer with Bob using the same OS account. When Alice uses your web application you will open <code>my-database</code> again and over-write Bob's data.</li>
</ul>

<p>
To mitigate these problems, we recommend the following algorithm (code is provided below as well implementing this):
</p>

<ol>
<li>Generate your Database or LocalServer name by using <code>window.location.href</code></li>
<li>Pre-pend the user's account name to the beginning of the string, followed by an underscore.</li>
<li>Pre-pend your application's name to the beginning, such as 'docs_'.
<li>Replace any characters that <a href="http://code.google.com/apis/gears/api_localserver.html#ManagedResourceStore">are not allowed</a> in the names so far by an underscore. Currently the name must consist only of visible ASCII characters excluding the following (spaces are also not allowed): / \ : * ? " &lt; &gt; | ; ,</li>
<li>If the string is longer than 64 characters, trim it to 64 characters (64 is the longest allowed name).</li>
</ol>

<p>
If you don't have a concept of a user for your application you can safely ignore pre-pending the username. An example Database or LocalServer name generated from this algorithm is <code>search_someuser_http___example_com_myapp</code>.
</p>

<p>
Here is code that implements this algorithm that you can use:
</p>

<pre class="prettyprint">
function getGearsName(appName, userName) {
var url = window.location.href;
url = url.replace(/#(.*)$/, ''); // remove anchor

var name = appName + '_' + (userName ? userName + '_' : '') + url;

// turn the following characters into underscores:
// / \ : * ? " &lt; &gt; | ; ,
// Gears should be able to allow spaces in db names but doesn't,
// so transform those too
name = name.replace(/\/|\\|:|\*|\?|\"|\&lt;|\&gt;|\||\;|\,|\.|\-|\=|[ ]/g, '_');

// Gears has a 64 character limit
name = name.substring(0, 63);

return name;
}
</pre>

<p>
Note that if your URLs are very long, and you have two Gears-based applications that are only differentiated near the end of the URL, that you might still get a name collision due to the length of a Gears name being restricted to 64 characters.
</p>

<p>
A final best practice is to use the following JavaScript idiom when working with a LocalServer; it makes your code a bit cleaner:
</p>

<pre class="prettyprint">
var server = google.gears.factory.create('beta.localserver');
var name = getGearsName('myApp', 'someUser');
var store = server.openManagedStore(name)
|| server.createManagedStore(name);
</pre>

<p>
Notice the <code>||</code>; rather than having to have a large <code>if</code> block, we first try to open a <a href="http://code.google.com/apis/gears/api_localserver.html#ManagedResourceStore">ManagedResourceStore</a> with the given name. If it doesn't exist then this method returns <code>false</code> and we short-circuit to the second part of the expression, which is to create a ManagedResourceStore with the given name.
</p>
</dd>

<dt id="storingData">
Best Practices for Storing Data on Users' Machines
</dt>

<dd>
<p>
If you are using the Gears <a href="http://code.google.com/apis/gears/api_database.html">Database</a> or the <a href="http://code.google.com/apis/gears/api_localserver.html#ManagedResourceStore">LocalServer</a> and are storing sensitive data on the local machine, you should make sure not to store your data on a public, sharable machine, such as at an Internet cafe. To ensure this, your application should do the following:
</p>

<ul>
<li>If a user turns on Gears, such as for offline ability or caching data, don't turn it on just for the user account. Instead, turn it on for this user <em>plus</em> the machine they are on. The best way to do this is to generate a <a href="http://en.wikipedia.org/wiki/GUID">GUID</a>, store it into the machine's Gears database, and then send this to the server. On the server you can save this GUID plus the account handle as being Gears enabled. If the user later uses your web application on a different machine, it will not be Gears enabled on that machine even though they are signed into the same account.</li>
<li>When the user enables the feature that uses Gears to store sensitive data, you should inform the user not to enable this on a shared, public machine. As an example, here is the dialog that <a href="http://www.myspace.com">MySpace</a> shows when activating the search feature of MySpace Mail, which uses Gears:<br />
<img src="resources/myspace_permission_dialog.png" />
</li>
</ul>

<p>
If your feature does not store sensitive data, such as the <a href="#startGearsSpeedUp">editor caching that <a href="http://www.wordpress.com">WordPress</a> does for faster access</a>, then you can safely ignore this Best Practice.
</p>
</dd>

<dt id="desktopShortcuts">
Best Practices for Desktop Shortcuts
</dt>

<dd>
<p>
The <a href="http://code.google.com/apis/gears/api_desktop.html">Desktop API</a> makes it easy for applications to drop a shortcut on to a user's desktop for quickly opening your web application. This is useful if you have an offline application and want to make it easy for the user to access it even when the network is not available.
</p>

<p>
Creating the Desktop API involved balancing both the interests of end-users and developers. We don't want to create a situation where a web-site can bother a user over and over to create a shortcut icon even when they don't want to. For this reason, we do not provide a way to query whether a desktop shortcut has been created before. Instead, we recommend the following:
</p>

<p>
When a user has indicated they would like to use your application offline by clicking on some user interface element (see <a href="#bestGearsPerms">Best Practices for Gears Permissioning</a> and <a href="#offlineUI">Best Practices for Offline User Interfaces</a>), your application should attempt to create a desktop icon by calling the Gears Desktop <code>createShortcut</code> method. This will cause the Gears permission prompt to appear. You should then store in the local Gears database that the user was given the option to create a desktop icon. Note that you aren't storing whether the user gave your website permission or not, since there is no way to know that. Instead, you are simply storing that the user has been prompted before.
</p>

<p>
Once this has been done, you should not prompt the user again. Instead, in the Settings pane for your application or another suitable area you should provide a button that says "Create Desktop Shortcut". When pressed, you can call the <code>createShortcut</code> method again to prompt the user to create a desktop icon again in case they changed their mind or deleted the old one and want to create it again.
</p>
</dd>

<dt id="versionDBSchema">
Best Practices for Versioning Database Schema
</dt>

<dd>
<p>
A common issue with Gears-based applications that will be deployed for a long period of time is evolving the client-side database schema. Here are some best practices and tips for doing this.
</p>

<p>
First, it is good to create a metadata table that versions your schema and optionally has the full <code>CREATE TABLE</code> SQL code in it for later reference. When you need to evolve your schema, iterate the version number and send over JavaScript that has an <code>upgradeDatabase</code> method that takes the new version number of the SQL to work with.
</p>

<p>
Inside this method, you should load the current version number and compare it against the new version number to know whether to upgrade or not. For example, if the schema on the client is version <code>2.5</code>, and the new version for the upgraded schema is <code>2.6</code>, then you know you need to upgrade this client. If they are the same then obviously you don't need to upgrade the schema.
</p>

<p>
Once you know you need to upgrade the schema, you should have different blocks where you can upgrade different old version numbers to the latest version; also make sure you surround the entire upgrade process in a transaction. Pseudocode:
</p>

<pre class="prettyprint">
// in our example we pass in 2.6 as the migrationVersion
function upgradeDatabase(migrationVersion) {
var db = google.gears.factory.create('beta.database');
db.open('my-db');

try {
// get the current version
var rs = db.execute('SELECT version FROM DATABASE_METADATA');
var currentVersion = rs.fieldByName('version');

// upgrade needed?
if (migrationVersion === currentVersion) {
db.close();
return;
}

// upgrade
db.execute('BEGIN TRANSACTION');

// do different upgrades for older versions
switch (currentVersion) {
case '2.4' :
// SQL to upgrade 2.4 to 2.5 goes here
break;
case '2.5' :
// SQL to upgrade 2.5 to 2.6 goes here
break;
}

// SQL to store newly updated version goes here; currentVersion
// should now be one version ahead

// recursively call method to upgrade to next version
upgradeDatabase(currentVersion)

db.execute('END TRANSACTION');
} finally {
if (rs) {
rs.close();
}
db.close();
}
}
</pre>

<p>
You can also create a corollary <code>downgradeDatabase</code> to downgrade the current database schema if necessary for a rollback.
</p>

<p>
An independent, non-Google open source library named <a href="http://m.ac.nz/gearshift/">Gearshift</a> is available to help with database migrations and schema versioning.
</p>
</dd>

<dt id="useMRS">
Best Practices for LocalServer
</dt>

<dd>
<p>
In most cases, use the <a href="http://code.google.com/apis/gears/api_localserver.html#ManagedResourceStore">ManagedResourceStore</a>. It is meant to be used for application resources such as CSS, HTML, JavaScript, and images. It is good because it enables you to push your updated application in one step to the clients.
</p>
<p>
The <a href="http://code.google.com/apis/gears/api_localserver.html#ResourceStore">ResourceStore</a> is meant to be more of a specialized tool and should be used accordingly. For instance, if your application has user-generated content or user-specific data then it would be difficult to control it with a ManagedResourceStore. Using a ResourceStore to handle this dynamic content is ideal.
</p>
</dd>

<dt id="syncing">
Best Practices for Syncing
</dt>

<dd>
<p>
As soon as you take an application offline (or use the Gears <a href="http://code.google.com/apis/gears/api_database.html">Database</a> to cache data for faster performance), you will run into the issue of syncing. Here are some tips and Best Practices for this situation.
</p>

<p>
First, the more you can avoid syncing the better. See <a href="#bestPracticeStartGears">Best Practices for Starting With Gears</a> to make sure you want to start with a web application that requires syncing. Gears can be used for many other uses that don't need syncing.
</p>

<p>
When it comes to syncing there is actually a spectrum of choices, ranging from easiest to hardest depending on the nature of your application. The following are some syncing scenarios from simplest to most complex; the further in the list you go the more challenging syncing becomes:
</p>

<ol>
<li>Read only throw away cache. This is a read-only cache stored in the local database that you throw away every time you sync. An example of this would be downloading a user's daily todo list, where every time you sync you throw away the local database's results and re-download all the new data.</li>
<li>Read only cache that you incrementally update with new data. This is a read only cache that you use offline or for performance; on syncs you download new data to append to this cache or partially replace the data that is present for greater efficiency. An example of this would be <a href="http://gearsblog.blogspot.com/2008/05/myspace-message-center-is-now-searching.html">MySpace Mail's usage of Gears</a>. At regular intervals MySpace Mail downloads a user's newest messages into the local database, keeping the old ones present to search over.</li>
<li>Read/write cache for single user. Data is downloaded and stored locally that originates from a single user. While offline a user can write to and update this data. When the user goes back online the data is synced. Since the data originates from a single-user the potential for conflict is less. However, keep in mind that a single-user can still be using Gears on multiple laptops, with offline data that might collide when they go back online. An example of this kind of data would be storing and writing emails while offline.</li>
<li>Read/write cache for multiple users without merging. In this scenario, users pull down data that is shared amongst multiple users. While offline they edit and change the data. When online the data is synced. Since the data is multi-user, the possibility exists that other users have changed the same data. In this scenario the syncing doesn't attempt to do automatic tricky conflict resolution and merging. For example, if user A edits the same document as user B, we would not try to merge the two documents together but rather have the last person who synced change the document. An example of this scenario is a collaborative, multi-user word processor such as <a href="http://zoho.com">Zoho</a>. Zoho, for example, does not attempt automatic merging of offline documents between multiple users.</li>
<li>Read/write cache for multiple users with automatic merging. This is the hardest. Data that has conflicts or were edited by multiple users are either automatically merged (which can be challenging for HTML documents, for example), or a conflict resolution UI is shown to the user where automatic merging can not be done.</li>
</ol>

<p>
When determining your syncing strategy, the more you can choose syncing scenarios that are near the top of the list above the easier things will be.
</p>

<p>
Handling these different scenarios requires different tools. Lets take a look at each.
</p>

<p id="syncReadThrowAway">
<em>Read only throw away cache</em>
</p>

<p>
As stated, this scenario is the simplest. At each sync cycle simply delete your local database and re-download all the data necessary to work offline.
</p>

<p id="syncReadUpdate">
<em>Read only cache that you incrementally update with new data</em>
</p>

<p>
First, in the local data that you download you should have a key of some kind that the server knows how to work with. For example, if you were downloading messages to store locally the server would want to include a <code>message_id</code> column that maps to a server-known ID to uniquely identify any messages that are downloaded.
</p>

<p>
Your sync sessions can be separated into three phases:
</p>

<ol>
<li>Download new data. This is where you download data that was not present before, simply appending rows to your tables.</li>
<li>Delete data. This is where you delete data that is no longer valid, possibly cleaning up references to these deleted rows from data that is still valid.</li>
<li>Update data. This is where the server foreign key comes in handy. The server can either send over JavaScript or JSON to update tables using the known keys or send over SQL to execute.
</ol>

<p>
If your application simply appends new data to an existing table without updating or invalidating existing data than you can ignore steps two and three.
</p>

<p>
Updating existing data is the trickest. The server can either send over JavaScript for the client to simply execute which will do the syncing, or send over SQL to execute on the client-side.
</p>

<p>
In the scenario where the server sends over JavaScript to run during syncing, imagine that we have a function named <code>updateContact</code> that can be called over and over in some JavaScript sent over from the server. This function takes the foreign key we identified earlier, such as a <code>contact_id</code> that is also present on the server, and then takes a list of column names to update along with the new values. During syncing imagine that the server sends the following, which you execute on the client-side by calling JavaScript's <code>eval</code> function:
</p>

<pre class="prettyprint">
updateContact(55, {first_name: 'Brad', favorite_color: 'blue'});
updateContact(100, {last_name: 'Jones'});
</pre>

<p>
A server could also send over SQL to execute against the client's local database:
</p>

<pre class="prettyprint">
db.execute('UPDATE CONTACT SET first_name = 'Brad', favorite_color = 'blue' WHERE contact_id = 55');
db.execute('UPDATE CONTACT SET last_name = 'Jones' WHERE contact_id = 100');
</pre>

<p id="syncReadWrite">
<em>Read/Write Scenarios</em>
</p>

<p>
As soon as you move into the write scenario it is best to move towards a transactional model where you keep a log of actions the user has done while offline, then replay this log when the network reappears.
</p>

<p>
The Dojo Offline tutorial has a good treatment on this topic <a href="http://docs.google.com/View?docid=dhkhksk4_8gdp9gr#sync">here</a>. Omar Kilani from <a href="http://www.rememberthemilk.com">Remember the Milk</a> describes their syncing strategy in a tutorial <a href="http://code.google.com/support/bin/answer.py?answer=73848&topic=11982">here</a>. An excerpt:
</p>

<blockquote>
<p>
Remember The Milk implements synchronization using a sorted action log that specifies which actions were taken offline and properties affected by these actions, and a local addition table that holds the locally assigned unique IDs (LUIDs) of any objects created by the client.
</p>

<p>
When synchronization is initiated, the client sends the action log and any local object additions to the server, which automatically handles conflicts. (Conflict resolution was already implemented in RTM to handle cases where multiple users may be working with the same task list.)
</p>

<p>
If there were client-side additions, the unique IDs assigned to those objects may differ from the IDs chosen by the server during the synchronization process. To account for this, the server sends the client a local-to-global ID map, which is used to remap the IDs of client-created in-memory objects and database entries to those on the server.
</p>

<p>
Once synchronization is finished, the client then requests the latest versions of its data set from the server to retrieve any server-side changes that occurred while the client was offline.
</p>

<p>
RTM attempts to synchronize with the server on every application launch (if connectivity is detected).
</p>
</blockquote>

<p id="syncSyncConstantly">
<em>The Always Syncing Model</em>
</p>

<p>
In some applications the best approach is to always operate with local data and sync periodically, independently of whether you are on- or offline. A great example of this is
<a href="http://gdata-javascript-client.googlecode.com/svn/trunk/samples/blogger/bloggears/bloggears.html">Blog.Gears</a>. More discussion on this model can be found <a href="http://code.google.com/apis/gears/architecture.html">here</a>.
</p>

<p id="syncWhenHowMuch">
<em>Deciding when and how much to sync</em>
</p>

<p>
Two more decisions remain to be made around syncing. First, you need to decide <em>when</em> to sync, and second, you must decide <em>how much</em> to sync and download.
</p>

<p>
Syncing can kick off:
</p>

<ul>
<li>Manually by the user with a sync button. This is the easiest to implement but puts the burden on the user. Its a good first choice to get running code quickly.</li>
<li>Automatically in the background at regular intervals and when the network reappears if offline.</li>
</ul>

<p>
You must also decide how much data to download. If the data set is small enough you can simply download all the data at once and then trickle in updates over time. If dealing with a large data set you will have to make intelligent choices about what to download. For example, if downloading a user's emails with an extremely large inbox you could choose to just download several thousand ranked by newest to oldest. If you want to download all of the data even with a large data set, you can choose to download an initial subset and then trickle down pieces of the remaining, older data at regular intervals in the background over time.
</p>

<p>
Finally, a number of open source frameworks exist which can help with syncing while using Gears:
</p>

<ul>
<li><a href="http://dojotoolkit.org/offline">Dojo Offline Toolkit</a></li>
<li><a href="http://code.google.com/p/trimpath/wiki/TrimJunction">Trimpath Junction</a></li>
</ul>
</dd>

<dt id="webAppAsDesktop">
Best Practices for Giving Web Applications Similar Features to Desktop Applications
</dt>

<dd>
<ul>
<li>
Use the
<a href="http://code.google.com/apis/gears/api_desktop.html">Desktop API</a>
to have an icon to your application. See <a href="#desktopShortcuts">Best Practices for Desktop Shortcuts</a> for details.
</li>
<li>
Refer to the <a href="#syncing">syncing best practices</a> to create a
seamless data syncing experience
</li>
<li>Operate on local data so the application is snappy</li>
<li>
Use <a href="http://code.google.com/apis/gears/api_localserver.html#ManagedResourceStore">ManagedResourceStore</a> to provide an auto-update mechanism for your
application
</li>
<li>Benefits of a web app as a desktop app:</li>
<ul>
<li>
One codebase vs. a desktop application's various client
(OS X, Linux, Windows) codebases
</li>
<li>
Easy auto-update mechanism
(updating JavaScript, HTML, CSS, manifest version number) vs. desktop
application's complicated software update process
</li>
</ul>
</ul>
</dd>

</div>
</body>
</html>
Show details Hide details

Change log

r3221 by gears.daemon on Feb 18, 2009   Diff
[Author: steveblock]

Prepares gears.google.com and Gears docs
for launch of Gears for Opera Mobile

This is very similar to CL 9387919, which
was rolled back in CL 9430877 pending
translation of strings for
gears.google.com.

R=andreip
CC=gears-internal
...
Go to: 
Project members, sign in to write a code review

Older revisions

r3192 by gears.daemon on Feb 04, 2009   Diff
[Author: steveblock]

Properly close <code> tag in
gears_faq.html.

...
r3115 by gears.daemon on Dec 16, 2008   Diff
[Author: steveblock]

This is a rollback of changelist
9387919 (Prepares gears.google.com and
Gears docs for launch of Gears for
...
r3104 by gears.daemon on Dec 12, 2008   Diff
[Author: steveblock]

Prepares gears.google.com and Gears
docs for launch of Gears for Opera
Mobile.
...
All revisions of this file

File info

Size: 127532 bytes, 2689 lines
Hosted by Google Code