firestone 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -36,7 +36,8 @@ or
36
36
 
37
37
  This currently only works on OSX.
38
38
 
39
- ### Create a new Firefox profile with a couple of custom preferences
39
+ ### Manage Firefox profiles
40
+ #### Profile Creation:
40
41
 
41
42
  require 'firefox'
42
43
  p = Firefox::Profile.create('./newprofile')
@@ -51,6 +52,15 @@ This currently only works on OSX.
51
52
  This will create a new firefox profile in `./newprofile`. It will populate the new profile's preferences with the values provided.
52
53
  If the given folder does not exist it will create it.
53
54
 
55
+ #### Profile Deletion:
56
+
57
+ require 'firefox'
58
+ Firefox::Profile.destroy('./newprofile')
59
+ # returns true if profile found and deleted, otherwise returns fase
60
+
61
+ This will delete all profile data and de-register the profile.
62
+ This is a non-reversible, destructive operation
63
+
54
64
  ## Suggestions, comments, bugs, whatever
55
65
  Feel free to use Issues to submit bugs, suggestions or feature requests.
56
66
 
@@ -1,5 +1,6 @@
1
- require "#{File.dirname(File.realpath(__FILE__))}/fondue"
2
- %W{ version base prefs profile addons installer }.each { |r| require "#{File.dirname(File.realpath(__FILE__))}/firefox/#{r}" }
1
+ %W{ fondue inifile }.each { |r| require File.join(File.dirname(File.realpath(__FILE__)),r) }
2
+ %W{ version base prefs profile addons installer }.each { |r| require File.join(File.dirname(File.realpath(__FILE__)),'firefox',r) }
3
+
3
4
  module Firefox
4
5
  def self.install!
5
6
  installer = Firefox::Installer.new(Firefox::Base.platform(RUBY_PLATFORM))
@@ -1,4 +1,7 @@
1
1
  module Firefox
2
+ # TODO: extension listing using <profile>/extensions.sqlite
3
+ # TODO: extension installation using zip/zip
4
+ # TODO: extension removal
2
5
  class Addons < Fondue::HashClass
3
6
  attr_accessor :path, :addons
4
7
 
@@ -19,7 +19,7 @@ module Firefox
19
19
  when :linux
20
20
  @bin_path = '/usr/bin/firefox'
21
21
  else
22
- raise UnsupportedOSError.new("I don't really know what OS you're on, sorry")
22
+ raise UnsupportedOSError, "I don't really know what OS you're on, sorry"
23
23
  end
24
24
  end
25
25
 
@@ -23,19 +23,66 @@ module Firefox
23
23
  # This is the right way to initialize a new profile.
24
24
  # It checks if the given directory exists, creates it if not
25
25
  def create path
26
+ ini = inifile.dup
26
27
  FileUtils.mkdir_p(path) unless File.directory?(path)
27
28
  FileUtils.touch(%W[prefs user].map { |f| File.join(path,"#{f}.js") })
28
- response = call_ff_create(path)
29
- if response =~ /Error/
30
- raise ProfileInitializationError, response
31
- else
32
- self.new(path)
29
+
30
+ last_entry_num = ini.sections.last.scan(/Profile([0-9]*)/).first.first.to_i
31
+ ini["Profile#{last_entry_num+1}"] = {
32
+ 'Name' => File.split(path).last,
33
+ 'IsRelative' => 0,
34
+ 'Path' => path
35
+ }
36
+ ini.write
37
+ new(path)
38
+ end
39
+
40
+ def destroy name
41
+ deleted = false
42
+ # delete profile form registry if name matches
43
+ inifile.sections.each do |section|
44
+ if inifile[section]['Name'] == name.to_s
45
+ FileUtils.rm_rf inifile[section]['Path']
46
+ inifile.delete_section(section)
47
+ deleted = true
48
+ end
49
+ end
50
+
51
+ # if we just deleted a profile, we need to renumber all other profiles
52
+ # so that firefox doesn't get confused and cries
53
+ if deleted
54
+ new_content = {}
55
+ i = 0
56
+ inifile.sections.each do |s|
57
+ if s =~ /Profile[0-9]*/
58
+ new_content["Profile#{i}"] = inifile[s]
59
+ inifile.delete_section(s)
60
+ i+=1
61
+ end
62
+ end
63
+ inifile.merge!(new_content)
33
64
  end
65
+
66
+ inifile.write
67
+ deleted
34
68
  end
35
69
 
36
- def call_ff_create path
37
- name = File.split(path).last
38
- %x[#{Base.bin_path} -CreateProfile \"#{name} #{File.realpath(path)}\" 2>&1]
70
+ def inifile reload = false
71
+ @inifile = IniFile.load(File.join(inifile_path(Base.platform(RUBY_PLATFORM)),'profiles.ini')) if @inifile.nil? or reload
72
+ @inifile
73
+ end
74
+
75
+ def inifile_path os
76
+ case os
77
+ when :osx
78
+ File.join('/','Users',ENV['USER'],'Library','Application Support','Firefox')
79
+ when :linux
80
+ File.join('/','home',ENV['USER'],'.mozilla','firefox')
81
+ when :win
82
+ File.join('C:','Documents and Settings',ENV['USER'],'Application Data','Mozilla','Firefox')
83
+ else
84
+ raise UnsupportedOSError, "I don't really know what OS you're on, sorry"
85
+ end
39
86
  end
40
87
  end
41
88
  end
@@ -1,3 +1,3 @@
1
1
  module Firefox
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -1,4 +1,4 @@
1
- %W{ version hash_class }.each { |r| require "#{File.dirname(File.realpath(__FILE__))}/fondue/#{r}" }
1
+ %W{ version hash_class }.each { |r| require File.join(File.dirname(File.realpath(__FILE__)),'fondue',r) }
2
2
 
3
3
  module Fondue
4
4
  end
@@ -0,0 +1,553 @@
1
+ #encoding: UTF-8
2
+ require 'strscan'
3
+ # [AC] Stolen from https://github.com/TwP/inifile/blob/master/lib/inifile.rb
4
+ # [AC] Had to tweak it a wee bit, as Firefox is very picky about ini file formatting
5
+ #
6
+ # This class represents the INI file and can be used to parse, modify,
7
+ # and write INI files.
8
+ #
9
+ class IniFile
10
+ include Enumerable
11
+
12
+ class Error < StandardError; end
13
+ VERSION = '2.0.2'
14
+
15
+ # Public: Open an INI file and load the contents.
16
+ #
17
+ # filename - The name of the fiel as a String
18
+ # opts - The Hash of options (default: {})
19
+ # :comment - String containing the comment character(s)
20
+ # :parameter - String used to separate parameter and value
21
+ # :encoding - Encoding String for reading / writing (Ruby 1.9)
22
+ # :escape - Boolean used to control character escaping
23
+ # :default - The String name of the default global section
24
+ #
25
+ # Examples
26
+ #
27
+ # IniFile.load('file.ini')
28
+ # #=> IniFile instance
29
+ #
30
+ # IniFile.load('does/not/exist.ini')
31
+ # #=> nil
32
+ #
33
+ # Returns an IniFile intsnace or nil if the file could not be opened.
34
+ #
35
+ def self.load( filename, opts = {} )
36
+ return unless File.file? filename
37
+ new(opts.merge(:filename => filename))
38
+ end
39
+
40
+ # Get and set the filename
41
+ attr_accessor :filename
42
+
43
+ # Get and set the encoding (Ruby 1.9)
44
+ attr_accessor :encoding
45
+
46
+ # Enable or disable character escaping
47
+ attr_accessor :escape
48
+
49
+ # Public: Create a new INI file from the given content String which
50
+ # contains the INI file lines. If the content are omitted, then the
51
+ # :filename option is used to read in the content of the INI file. If
52
+ # neither the content for a filename is provided then an empty INI file is
53
+ # created.
54
+ #
55
+ # content - The String containing the INI file contents
56
+ # opts - The Hash of options (default: {})
57
+ # :comment - String containing the comment character(s)
58
+ # :parameter - String used to separate parameter and value
59
+ # :encoding - Encoding String for reading / writing (Ruby 1.9)
60
+ # :escape - Boolean used to control character escaping
61
+ # :default - The String name of the default global section
62
+ # :filename - The filename as a String
63
+ #
64
+ # Examples
65
+ #
66
+ # IniFile.new
67
+ # #=> an empty IniFile instance
68
+ #
69
+ # IniFile.new( "[global]\nfoo=bar" )
70
+ # #=> an IniFile instance
71
+ #
72
+ # IniFile.new( :filename => 'file.ini', :encoding => 'UTF-8' )
73
+ # #=> an IniFile instance
74
+ #
75
+ # IniFile.new( "[global]\nfoo=bar", :comment => '#' )
76
+ # #=> an IniFile instance
77
+ #
78
+ def initialize( content = nil, opts = {} )
79
+ opts, content = content, nil if Hash === content
80
+
81
+ @content = content
82
+
83
+ @comment = opts.fetch(:comment, ';#')
84
+ @param = opts.fetch(:parameter, '=')
85
+ @encoding = opts.fetch(:encoding, nil)
86
+ @escape = opts.fetch(:escape, true)
87
+ @default = opts.fetch(:default, 'global')
88
+ @filename = opts.fetch(:filename, nil)
89
+
90
+ @ini = Hash.new {|h,k| h[k] = Hash.new}
91
+
92
+ if @content then parse!
93
+ elsif @filename then read
94
+ end
95
+ end
96
+
97
+ # Public: Write the contents of this IniFile to the file system. If left
98
+ # unspecified, the currently configured filename and encoding will be used.
99
+ # Otherwise the filename and encoding can be specified in the options hash.
100
+ #
101
+ # opts - The default options Hash
102
+ # :filename - The filename as a String
103
+ # :encoding - The encoding as a String (Ruby 1.9)
104
+ #
105
+ # Returns this IniFile instance.
106
+ #
107
+ def write( opts = {} )
108
+ filename = opts.fetch(:filename, @filename)
109
+ encoding = opts.fetch(:encoding, @encoding)
110
+ mode = (RUBY_VERSION >= '1.9' && encoding) ?
111
+ "w:#{encoding.to_s}" :
112
+ 'w'
113
+
114
+ File.open(filename, mode) do |f|
115
+ @ini.each do |section,hash|
116
+ f.puts "[#{section}]"
117
+ hash.each {|param,val| f.puts "#{param}#{@param}#{escape_value val}"}
118
+ f.puts
119
+ end
120
+ end
121
+
122
+ self
123
+ end
124
+ alias :save :write
125
+
126
+ # Public: Read the contents of the INI file from the file system and replace
127
+ # and set the state of this IniFile instance. If left unspecified the
128
+ # currently configured filename and encoding will be used when reading from
129
+ # the file system. Otherwise the filename and encoding can be specified in
130
+ # the options hash.
131
+ #
132
+ # opts - The default options Hash
133
+ # :filename - The filename as a String
134
+ # :encoding - The encoding as a String (Ruby 1.9)
135
+ #
136
+ # Returns this IniFile instance if the read was successful; nil is returned
137
+ # if the file could not be read.
138
+ #
139
+ def read( opts = {} )
140
+ filename = opts.fetch(:filename, @filename)
141
+ encoding = opts.fetch(:encoding, @encoding)
142
+ return unless File.file? filename
143
+
144
+ mode = (RUBY_VERSION >= '1.9' && encoding) ?
145
+ "r:#{encoding.to_s}" :
146
+ 'r'
147
+ fd = File.open(filename, mode)
148
+ @content = fd.read
149
+
150
+ parse!
151
+ self
152
+ ensure
153
+ fd.close if fd && !fd.closed?
154
+ end
155
+ alias :restore :read
156
+
157
+ # Returns this IniFile converted to a String.
158
+ #
159
+ def to_s
160
+ s = []
161
+ @ini.each do |section,hash|
162
+ s << "[#{section}]"
163
+ hash.each {|param,val| s << "#{param} #{@param} #{escape_value val}"}
164
+ s << ""
165
+ end
166
+ s.join("\n")
167
+ end
168
+
169
+ # Returns this IniFile converted to a Hash.
170
+ #
171
+ def to_h
172
+ @ini.dup
173
+ end
174
+
175
+ # Public: Creates a copy of this inifile with the entries from the
176
+ # other_inifile merged into the copy.
177
+ #
178
+ # other - The other IniFile.
179
+ #
180
+ # Returns a new IniFile.
181
+ #
182
+ def merge( other )
183
+ self.dup.merge!(other)
184
+ end
185
+
186
+ # Public: Merges other_inifile into this inifile, overwriting existing
187
+ # entries. Useful for having a system inifile with user over-ridable settings
188
+ # elsewhere.
189
+ #
190
+ # other - The other IniFile.
191
+ #
192
+ # Returns this IniFile.
193
+ #
194
+ def merge!( other )
195
+ my_keys = @ini.keys
196
+ other_keys =
197
+ case other
198
+ when IniFile; other.instance_variable_get(:@ini).keys
199
+ when Hash; other.keys
200
+ else raise "cannot merge contents from '#{other.class.name}'" end
201
+
202
+ (my_keys & other_keys).each do |key|
203
+ @ini[key].merge!(other[key])
204
+ end
205
+
206
+ (other_keys - my_keys).each do |key|
207
+ @ini[key] = other[key]
208
+ end
209
+
210
+ self
211
+ end
212
+
213
+ # Public: Yield each INI file section, parameter, and value in turn to the
214
+ # given block.
215
+ #
216
+ # block - The block that will be iterated by the each method. The block will
217
+ # be passed the current section and the parameter / value pair.
218
+ #
219
+ # Examples
220
+ #
221
+ # inifile.each do |section, parameter, value|
222
+ # puts "#{parameter} = #{value} [in section - #{section}]"
223
+ # end
224
+ #
225
+ # Returns this IniFile.
226
+ #
227
+ def each
228
+ return unless block_given?
229
+ @ini.each do |section,hash|
230
+ hash.each do |param,val|
231
+ yield section, param, val
232
+ end
233
+ end
234
+ self
235
+ end
236
+
237
+ # Public: Yield each section in turn to the given block.
238
+ #
239
+ # block - The block that will be iterated by the each method. The block will
240
+ # be passed the current section as a Hash.
241
+ #
242
+ # Examples
243
+ #
244
+ # inifile.each_section do |section|
245
+ # puts section.inspect
246
+ # end
247
+ #
248
+ # Returns this IniFile.
249
+ #
250
+ def each_section
251
+ return unless block_given?
252
+ @ini.each_key {|section| yield section}
253
+ self
254
+ end
255
+
256
+ # Public: Remove a section identified by name from the IniFile.
257
+ #
258
+ # section - The section name as a String.
259
+ #
260
+ # Returns the deleted section Hash.
261
+ #
262
+ def delete_section( section )
263
+ @ini.delete section.to_s
264
+ end
265
+
266
+ # Public: Get the section Hash by name. If the section does not exist, then
267
+ # it will be created.
268
+ #
269
+ # section - The section name as a String.
270
+ #
271
+ # Examples
272
+ #
273
+ # inifile['global']
274
+ # #=> global section Hash
275
+ #
276
+ # Returns the Hash of parameter/value pairs for this section.
277
+ #
278
+ def []( section )
279
+ return nil if section.nil?
280
+ @ini[section.to_s]
281
+ end
282
+
283
+ # Public: Set the section to a hash of parameter/value pairs.
284
+ #
285
+ # section - The section name as a String.
286
+ # value - The Hash of parameter/value pairs.
287
+ #
288
+ # Examples
289
+ #
290
+ # inifile['tenderloin'] = { 'gritty' => 'yes' }
291
+ # #=> { 'gritty' => 'yes' }
292
+ #
293
+ # Returns the value Hash.
294
+ #
295
+ def []=( section, value )
296
+ @ini[section.to_s] = value
297
+ end
298
+
299
+ # Public: Create a Hash containing only those INI file sections whose names
300
+ # match the given regular expression.
301
+ #
302
+ # regex - The Regexp used to match section names.
303
+ #
304
+ # Examples
305
+ #
306
+ # inifile.match(/^tree_/)
307
+ # #=> Hash of matching sections
308
+ #
309
+ # Return a Hash containing only those sections that match the given regular
310
+ # expression.
311
+ #
312
+ def match( regex )
313
+ @ini.dup.delete_if { |section, _| section !~ regex }
314
+ end
315
+
316
+ # Public: Check to see if the IniFile contains the section.
317
+ #
318
+ # section - The section name as a String.
319
+ #
320
+ # Returns true if the section exists in the IniFile.
321
+ #
322
+ def has_section?( section )
323
+ @ini.has_key? section.to_s
324
+ end
325
+
326
+ # Returns an Array of section names contained in this IniFile.
327
+ #
328
+ def sections
329
+ @ini.keys
330
+ end
331
+
332
+ # Public: Freeze the state of this IniFile object. Any attempts to change
333
+ # the object will raise an error.
334
+ #
335
+ # Returns this IniFile.
336
+ #
337
+ def freeze
338
+ super
339
+ @ini.each_value {|h| h.freeze}
340
+ @ini.freeze
341
+ self
342
+ end
343
+
344
+ # Public: Mark this IniFile as tainted -- this will traverse each section
345
+ # marking each as tainted.
346
+ #
347
+ # Returns this IniFile.
348
+ #
349
+ def taint
350
+ super
351
+ @ini.each_value {|h| h.taint}
352
+ @ini.taint
353
+ self
354
+ end
355
+
356
+ # Public: Produces a duplicate of this IniFile. The duplicate is independent
357
+ # of the original -- i.e. the duplicate can be modified without changing the
358
+ # original. The tainted state of the original is copied to the duplicate.
359
+ #
360
+ # Returns a new IniFile.
361
+ #
362
+ def dup
363
+ other = super
364
+ other.instance_variable_set(:@ini, Hash.new {|h,k| h[k] = Hash.new})
365
+ @ini.each_pair {|s,h| other[s].merge! h}
366
+ other.taint if self.tainted?
367
+ other
368
+ end
369
+
370
+ # Public: Produces a duplicate of this IniFile. The duplicate is independent
371
+ # of the original -- i.e. the duplicate can be modified without changing the
372
+ # original. The tainted state and the frozen state of the original is copied
373
+ # to the duplicate.
374
+ #
375
+ # Returns a new IniFile.
376
+ #
377
+ def clone
378
+ other = dup
379
+ other.freeze if self.frozen?
380
+ other
381
+ end
382
+
383
+ # Public: Compare this IniFile to some other IniFile. For two INI files to
384
+ # be equivalent, they must have the same sections with the same parameter /
385
+ # value pairs in each section.
386
+ #
387
+ # other - The other IniFile.
388
+ #
389
+ # Returns true if the INI files are equivalent and false if they differ.
390
+ #
391
+ def eql?( other )
392
+ return true if equal? other
393
+ return false unless other.instance_of? self.class
394
+ @ini == other.instance_variable_get(:@ini)
395
+ end
396
+ alias :== :eql?
397
+
398
+
399
+ private
400
+
401
+ # Parse the ini file contents. This will clear any values currently stored
402
+ # in the ini hash.
403
+ #
404
+ def parse!
405
+ return unless @content
406
+
407
+ string = ''
408
+ property = ''
409
+
410
+ @ini.clear
411
+ @_line = nil
412
+ @_section = nil
413
+
414
+ scanner = StringScanner.new(@content)
415
+ until scanner.eos?
416
+
417
+ # keep track of the current line for error messages
418
+ @_line = scanner.check(%r/\A.*$/) if scanner.bol?
419
+
420
+ # look for escaped special characters \# \" etc
421
+ if scanner.scan(%r/\\([\[\]#{@param}#{@comment}"])/)
422
+ string << scanner[1]
423
+
424
+ # look for quoted strings
425
+ elsif scanner.scan(%r/"/)
426
+ quote = scanner.scan_until(/(?:\A|[^\\])"/)
427
+ parse_error('Unmatched quote') if quote.nil?
428
+
429
+ quote.chomp!('"')
430
+ string << quote
431
+
432
+ # look for comments, empty strings, end of lines
433
+ elsif scanner.skip(%r/\A\s*(?:[#{@comment}].*)?$/)
434
+ string << scanner.getch unless scanner.eos?
435
+
436
+ process_property(property, string)
437
+
438
+ # look for the separator between property name and value
439
+ elsif scanner.scan(%r/#{@param}/)
440
+ if property.empty?
441
+ property = string.strip
442
+ string.slice!(0, string.length)
443
+ else
444
+ parse_error
445
+ end
446
+
447
+ # look for the start of a new section
448
+ elsif scanner.scan(%r/\A\s*\[([^\]]+)\]/)
449
+ @_section = @ini[scanner[1]]
450
+
451
+ # otherwise scan and store characters till we hit the start of some
452
+ # special section like a quote, newline, comment, etc.
453
+ else
454
+ tmp = scanner.scan_until(%r/([\n"#{@param}#{@comment}] | \z | \\[\[\]#{@param}#{@comment}"])/mx)
455
+ parse_error if tmp.nil?
456
+
457
+ len = scanner[1].length
458
+ tmp.slice!(tmp.length - len, len)
459
+
460
+ scanner.pos = scanner.pos - len
461
+ string << tmp
462
+ end
463
+ end
464
+
465
+ process_property(property, string)
466
+ end
467
+
468
+ # Store the property / value pair in the currently active section. This
469
+ # method checks for continuation of the value to the next line.
470
+ #
471
+ # property - The property name as a String.
472
+ # value - The property value as a String.
473
+ #
474
+ # Returns nil.
475
+ #
476
+ def process_property( property, value )
477
+ value.chomp!
478
+ return if property.empty? and value.empty?
479
+ return if value.sub!(%r/\\\s*\z/, '')
480
+
481
+ property.strip!
482
+ value.strip!
483
+
484
+ parse_error if property.empty?
485
+
486
+ current_section[property.dup] = unescape_value(value.dup)
487
+
488
+ property.slice!(0, property.length)
489
+ value.slice!(0, value.length)
490
+
491
+ nil
492
+ end
493
+
494
+ # Returns the current section Hash.
495
+ #
496
+ def current_section
497
+ @_section ||= @ini[@default]
498
+ end
499
+
500
+ # Raise a parse error using the given message and appending the current line
501
+ # being parsed.
502
+ #
503
+ # msg - The message String to use.
504
+ #
505
+ # Raises IniFile::Error
506
+ #
507
+ def parse_error( msg = 'Could not parse line' )
508
+ raise Error, "#{msg}: #{@_line.inspect}"
509
+ end
510
+
511
+ # Unescape special characters found in the value string. This will convert
512
+ # escaped null, tab, carriage return, newline, and backslash into their
513
+ # literal equivalents.
514
+ #
515
+ # value - The String value to unescape.
516
+ #
517
+ # Returns the unescaped value.
518
+ #
519
+ def unescape_value( value )
520
+ return value unless @escape
521
+
522
+ value = value.to_s
523
+ value.gsub!(%r/\\[0nrt\\]/) { |char|
524
+ case char
525
+ when '\0'; "\0"
526
+ when '\n'; "\n"
527
+ when '\r'; "\r"
528
+ when '\t'; "\t"
529
+ when '\\\\'; "\\"
530
+ end
531
+ }
532
+ value
533
+ end
534
+
535
+ # Escape special characters.
536
+ #
537
+ # value - The String value to escape.
538
+ #
539
+ # Returns the escaped value.
540
+ #
541
+ def escape_value( value )
542
+ return value unless @escape
543
+
544
+ value = value.to_s.dup
545
+ value.gsub!(%r/\\([0nrt])/, '\\\\\1')
546
+ value.gsub!(%r/\n/, '\n')
547
+ value.gsub!(%r/\r/, '\r')
548
+ value.gsub!(%r/\t/, '\t')
549
+ value.gsub!(%r/\0/, '\0')
550
+ value
551
+ end
552
+
553
+ end # IniFile
@@ -0,0 +1,33 @@
1
+ [General]
2
+ StartWithLastProfile=1
3
+
4
+ [Profile0]
5
+ Name=default
6
+ IsRelative=1
7
+ Path=Profiles/yoyoma.default
8
+
9
+ [Profile1]
10
+ Name=2220
11
+ IsRelative=0
12
+ Path=./spec/files/profiles/2220
13
+
14
+ [Profile2]
15
+ Name=2221
16
+ IsRelative=0
17
+ Path=./spec/files/profiles/2221
18
+
19
+ [Profile3]
20
+ Name=2240
21
+ IsRelative=0
22
+ Path=./spec/files/profiles/2240
23
+
24
+ [Profile4]
25
+ Name=2241
26
+ IsRelative=0
27
+ Path=./spec/files/profiles/2241
28
+
29
+ [Profile5]
30
+ Name=2242
31
+ IsRelative=0
32
+ Path=./spec/files/profiles/2242
33
+
@@ -2,26 +2,70 @@ require 'spec_helper'
2
2
 
3
3
  describe Firefox::Profile do
4
4
  before { @path = './spec/files/' }
5
+ subject { Firefox::Profile }
5
6
 
6
- context '#register_profile' do
7
+ context '#inifile_path' do
8
+ it { subject.inifile_path(:osx).should eq("/Users/#{ENV['USER']}/Library/Application Support/Firefox") }
9
+ it { subject.inifile_path(:win).should eq("C:/Documents and Settings/#{ENV['USER']}/Application Data/Mozilla/Firefox") }
10
+ it { subject.inifile_path(:linux).should eq("/home/#{ENV['USER']}/.mozilla/firefox") }
11
+ end
12
+
13
+ context '#inifile' do
14
+ before { Firefox::Profile.stub(:inifile_path).and_return('./spec/files/') }
15
+
16
+ it { subject.inifile.should be_a(IniFile) }
17
+ it { subject.inifile['General']['StartWithLastProfile'].should eq("1") }
18
+ end
19
+
20
+ context '#create' do
7
21
  before {
22
+ @inifile = './spec/files/profiles.ini'
23
+ @old_inifile = File.read(@inifile)
8
24
  @path = './spec/files/testprofile'
9
- Firefox::Profile.stub(:call_ff_create).and_return("Success: created profile 'test /Users/achilles/Scripts/serpclicker/profiles/' at '/Users/achilles/Scripts/serpclicker/profiles/prefs.js'")
25
+ Firefox::Profile.stub(:inifile_path).and_return('./spec/files/')
26
+ }
27
+ after {
28
+ FileUtils.rm_rf @path
29
+ File.open(@inifile,'w') {|f| f.write(@old_inifile)}
10
30
  }
11
- after { FileUtils.rm_rf @path }
12
31
  subject { Firefox::Profile.create(@path) }
13
32
 
14
33
  it { subject.should be_a(Firefox::Profile) }
15
- it "saves prefs on save" do
34
+
35
+ it 'saves prefs on save' do
16
36
  subject.prefs.merge!({ :test => true })
17
37
  subject.save!
18
38
 
19
39
  n = Firefox::Profile.new(@path)
20
40
  n.prefs.prefs.should eq({ "test" => true })
21
41
  end
42
+
43
+ it 'updates ini file' do
44
+ subject
45
+ inifile = IniFile.load(@inifile)
46
+ inifile.sections.last.should eq('Profile6')
47
+ inifile['Profile6']['Name'].should eq('testprofile')
48
+ end
22
49
  end
23
50
 
24
- subject { Firefox::Profile.new(@path) }
25
- it { subject.prefs.should be_a(Firefox::Prefs) }
26
- it { subject.addons.should be_a(Firefox::Addons) }
51
+ context "#destroy" do
52
+ before {
53
+ @inifile = './spec/files/profiles.ini'
54
+ @old_inifile = File.read(@inifile)
55
+ Firefox::Profile.stub(:inifile_path).and_return('./spec/files/') }
56
+ after { File.open(@inifile,'w') {|f| f.write(@old_inifile)} }
57
+
58
+ it 'should reorder profiles' do
59
+ subject.destroy(2240).should eq(true)
60
+ subject.inifile.sections.size.should eq(6)
61
+ subject.inifile.sections.include?('Profile5').should eq(false)
62
+ end
63
+ end
64
+
65
+ context 'associations' do
66
+ subject { Firefox::Profile.new(@path) }
67
+
68
+ it { subject.prefs.should be_a(Firefox::Prefs) }
69
+ it { subject.addons.should be_a(Firefox::Addons) }
70
+ end
27
71
  end
data/test.rb ADDED
@@ -0,0 +1,3 @@
1
+ require './lib/firefox'
2
+ i = Firefox::Installer.new(:osx,nil,'18.0.2', :dmg => '/var/folders/9p/n54h7qmx57351_by82lh77d40000gn/T/firefox.dmg')
3
+ i.install!
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: firestone
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-17 00:00:00.000000000Z
12
+ date: 2013-02-18 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: progressbar
16
- requirement: &2161532540 !ruby/object:Gem::Requirement
16
+ requirement: &2157028880 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2161532540
24
+ version_requirements: *2157028880
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec
27
- requirement: &2161532120 !ruby/object:Gem::Requirement
27
+ requirement: &2157028460 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,7 +32,7 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *2161532120
35
+ version_requirements: *2157028460
36
36
  description: A collection of Firefox automation and programmatic management scripts
37
37
  in Ruby
38
38
  email:
@@ -57,12 +57,15 @@ files:
57
57
  - lib/fondue.rb
58
58
  - lib/fondue/hash_class.rb
59
59
  - lib/fondue/version.rb
60
+ - lib/inifile.rb
60
61
  - spec/addons_spec.rb
61
62
  - spec/files/prefs.js
63
+ - spec/files/profiles.ini
62
64
  - spec/hash_class_spec.rb
63
65
  - spec/prefs_spec.rb
64
66
  - spec/profile_spec.rb
65
67
  - spec/spec_helper.rb
68
+ - test.rb
66
69
  homepage: http://humbuckercode.co.uk/licks/gems/firestone
67
70
  licenses: []
68
71
  post_install_message:
@@ -91,6 +94,7 @@ summary: A collection of Firefox automation and programmatic management scripts
91
94
  test_files:
92
95
  - spec/addons_spec.rb
93
96
  - spec/files/prefs.js
97
+ - spec/files/profiles.ini
94
98
  - spec/hash_class_spec.rb
95
99
  - spec/prefs_spec.rb
96
100
  - spec/profile_spec.rb