vapir-firefox 1.9.0 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/vapir-firefox/browser.rb +73 -25
- data/lib/vapir-firefox/element.rb +5 -5
- data/lib/vapir-firefox/firefox_socket/base.rb +8 -7
- data/lib/vapir-firefox/javascript_object.rb +26 -3
- data/lib/vapir-firefox/modal_dialog.rb +5 -4
- data/lib/vapir-firefox/page_container.rb +16 -5
- data/lib/vapir-firefox/version.rb +1 -1
- data/lib/vapir-firefox/window.rb +1 -1
- metadata +6 -15
@@ -187,7 +187,7 @@ module Vapir
|
|
187
187
|
# socket may be dead, and you want a new one. a warning will be printed if this occurs.
|
188
188
|
def self.firefox_socket(options={}) # :nodoc:
|
189
189
|
if options[:reset] || !(class_variable_defined?('@@firefox_socket') && @@firefox_socket)
|
190
|
-
initialize_firefox_socket(options[:socket_class], options[:socket_options])
|
190
|
+
initialize_firefox_socket(options[:socket_class] || firefox_socket_class, options[:socket_options] || firefox_socket_class_options)
|
191
191
|
end
|
192
192
|
if options[:reset_if_dead]
|
193
193
|
begin
|
@@ -268,7 +268,7 @@ module Vapir
|
|
268
268
|
|
269
269
|
@pid = begin
|
270
270
|
self.pid
|
271
|
-
rescue
|
271
|
+
rescue CannotHandlePid
|
272
272
|
nil
|
273
273
|
end
|
274
274
|
|
@@ -282,7 +282,6 @@ module Vapir
|
|
282
282
|
find_window(how, what)
|
283
283
|
end
|
284
284
|
end
|
285
|
-
set_browser_document
|
286
285
|
else
|
287
286
|
open_window
|
288
287
|
end
|
@@ -294,8 +293,8 @@ module Vapir
|
|
294
293
|
wait if options[:wait]
|
295
294
|
end
|
296
295
|
|
297
|
-
def
|
298
|
-
'MozillaUIWindowClass'
|
296
|
+
def mozilla_window_class_names
|
297
|
+
['MozillaUIWindowClass', 'MozillaWindowClass']
|
299
298
|
end
|
300
299
|
|
301
300
|
def browser
|
@@ -413,7 +412,6 @@ module Vapir
|
|
413
412
|
@document_object=browser_object.contentDocument
|
414
413
|
@content_window_object=browser_object.contentWindow
|
415
414
|
# note that browser_window_object.content is the same thing, but simpler to refer to stuff on browser_object since that is updated by the nsIWebProgressListener below
|
416
|
-
@body_object=document_object.body
|
417
415
|
@browser_objects[:requests_in_progress]=[]
|
418
416
|
@requests_in_progress=@browser_objects[:requests_in_progress].to_array
|
419
417
|
@browser_objects[:unmatched_stopped_requests_count]=0
|
@@ -481,7 +479,9 @@ module Vapir
|
|
481
479
|
attr_reader :content_window_object
|
482
480
|
attr_reader :browser_object
|
483
481
|
attr_reader :document_object
|
484
|
-
|
482
|
+
def body_object
|
483
|
+
document_object.body
|
484
|
+
end
|
485
485
|
|
486
486
|
def updated_at
|
487
487
|
Time.at(@updated_at_epoch_ms.val/1000.0)+@updated_at_offset
|
@@ -517,7 +517,7 @@ module Vapir
|
|
517
517
|
end
|
518
518
|
end
|
519
519
|
|
520
|
-
@browser_window_object=@browser_object=@document_object=@content_window_object
|
520
|
+
@browser_window_object=@browser_object=@document_object=@content_window_object=nil
|
521
521
|
if @self_launched_browser && firefox_socket && !self.class.window_objects.any?{ true }
|
522
522
|
quit_browser(:force => false)
|
523
523
|
end
|
@@ -540,7 +540,7 @@ module Vapir
|
|
540
540
|
|
541
541
|
pid = @pid || begin
|
542
542
|
self.pid
|
543
|
-
rescue
|
543
|
+
rescue CannotHandlePid
|
544
544
|
nil
|
545
545
|
end
|
546
546
|
|
@@ -557,20 +557,24 @@ module Vapir
|
|
557
557
|
|
558
558
|
wait_for_process_exit(pid)
|
559
559
|
|
560
|
-
@browser_window_object=@browser_object=@document_object=@content_window_object
|
560
|
+
@browser_window_object=@browser_object=@document_object=@content_window_object=nil
|
561
561
|
nil
|
562
562
|
end
|
563
563
|
|
564
|
+
# class representing an inability to either retrieve or check the status of firefox's pid
|
565
|
+
class CannotHandlePid < StandardError; end
|
566
|
+
|
564
567
|
# returns the pid of the currently-attached Firefox process.
|
565
568
|
#
|
566
569
|
# This only works on Firefox >= 3.6, on platforms supported (see #current_os), and raises
|
567
|
-
#
|
570
|
+
# CannotHandlePid if it can't get the pid.
|
568
571
|
def pid
|
569
572
|
begin
|
573
|
+
raise CannotHandlePid unless firefox_socket.host == 'localhost'
|
570
574
|
begin
|
571
575
|
ctypes = firefox_socket.Components.utils.import("resource://gre/modules/ctypes.jsm").ctypes
|
572
576
|
rescue FirefoxSocketJavascriptError
|
573
|
-
raise
|
577
|
+
raise CannotHandlePid, "Firefox 3.6 or greater is required for this method.\n\nOriginal error from firefox: #{$!.class}: #{$!.message}", $!.backtrace
|
574
578
|
end
|
575
579
|
lib, pidfunction, abi = *case current_os
|
576
580
|
when :macosx
|
@@ -588,7 +592,7 @@ module Vapir
|
|
588
592
|
# see https://bugzilla.mozilla.org/show_bug.cgi?id=585175
|
589
593
|
['kernel32', 'GetCurrentProcessId', ctypes['winapi_abi'] || ctypes['stdcall_abi']]
|
590
594
|
else
|
591
|
-
raise
|
595
|
+
raise CannotHandlePid, "don't know how to get pid for #{current_os}"
|
592
596
|
end
|
593
597
|
lib = ctypes.open(lib)
|
594
598
|
begin
|
@@ -600,9 +604,16 @@ module Vapir
|
|
600
604
|
end
|
601
605
|
end
|
602
606
|
|
607
|
+
# returns the host which will be configured for a socket. same as firefox_socket.host,
|
608
|
+
# if that exist, but this is correct even if firefox_socket isn't initialized.
|
609
|
+
def firefox_socket_host
|
610
|
+
firefox_socket_class_options['host'] || firefox_socket_class.config.host
|
611
|
+
end
|
612
|
+
|
603
613
|
# attempts to determine whether the given process is still running. will raise
|
604
|
-
#
|
614
|
+
# CannotHandlePid if it can't determine this.
|
605
615
|
def process_running?(pid)
|
616
|
+
raise CannotHandlePid unless firefox_socket_host == 'localhost'
|
606
617
|
case current_os
|
607
618
|
when :windows
|
608
619
|
kernel32 = Vapir::Firefox.instance_eval do # define this on the class for reuse
|
@@ -630,7 +641,7 @@ module Vapir
|
|
630
641
|
`ps -p #{pid}`
|
631
642
|
$? == 0
|
632
643
|
else
|
633
|
-
raise
|
644
|
+
raise CannotHandlePid
|
634
645
|
end
|
635
646
|
end
|
636
647
|
|
@@ -800,12 +811,36 @@ module Vapir
|
|
800
811
|
|
801
812
|
# the HTTP response status code for the currently loaded document
|
802
813
|
def response_status_code
|
814
|
+
current_document_channel_object.responseStatus
|
815
|
+
end
|
816
|
+
# a hash of the response headers returned for the currently loaded document
|
817
|
+
def response_headers
|
818
|
+
firefox_socket.call_function(:channel => current_document_channel_object) do %Q{
|
819
|
+
var headers={};
|
820
|
+
channel.visitResponseHeaders({visitHeader: function(header, value){ headers[header]=value; }});
|
821
|
+
return headers;
|
822
|
+
}
|
823
|
+
end.val.freeze
|
824
|
+
end
|
825
|
+
# a hash of the request headers the browser sent for the currently loaded document
|
826
|
+
def request_headers
|
827
|
+
firefox_socket.call_function(:channel => current_document_channel_object) do %Q{
|
828
|
+
var headers={};
|
829
|
+
channel.visitRequestHeaders({visitHeader: function(header, value){ headers[header]=value; }});
|
830
|
+
return headers;
|
831
|
+
}
|
832
|
+
end.val.freeze
|
833
|
+
end
|
834
|
+
# a nsIHttpChannel for the currently loaded document - the browser's docShell.currentDocumentChannel
|
835
|
+
#
|
836
|
+
# see https://developer.mozilla.org/en/XPCOM_Interface_Reference/nsIHttpChannel
|
837
|
+
def current_document_channel_object
|
803
838
|
channel = nil
|
804
839
|
::Waiter.try_for(8, :exception => nil) do
|
805
840
|
channel=browser.browser_object.docShell.currentDocumentChannel
|
806
841
|
channel.is_a?(JavascriptObject) && channel.instanceof(browser.firefox_socket.Components.interfaces.nsIHttpChannel) && channel.respond_to?(:responseStatus)
|
807
842
|
end || raise(RuntimeError, "expected currentDocumentChannel to exist and be a nsIHttpChannel but it wasn't; was #{channel.is_a?(JavascriptObject) ? channel.toString : channel.inspect}")
|
808
|
-
|
843
|
+
channel
|
809
844
|
end
|
810
845
|
|
811
846
|
# Maximize the current browser window.
|
@@ -820,6 +855,7 @@ module Vapir
|
|
820
855
|
|
821
856
|
# Waits for the page to get loaded.
|
822
857
|
def wait(options={})
|
858
|
+
return unless config.wait
|
823
859
|
return unless exists?
|
824
860
|
unless options.is_a?(Hash)
|
825
861
|
raise ArgumentError, "given options should be a Hash, not #{options.inspect} (#{options.class})\nold conflicting arguments of no_sleep or last_url are gone"
|
@@ -833,9 +869,9 @@ module Vapir
|
|
833
869
|
# If the redirect is to a download attachment that does not reload this page, this
|
834
870
|
# method will loop forever. Therefore, we need to ensure that if this method is called
|
835
871
|
# twice with the same URL, we simply accept that we're done.
|
836
|
-
url= document_object
|
872
|
+
url= document_object['URL']
|
837
873
|
|
838
|
-
if(url != options[:last_url])
|
874
|
+
if(url && url != options[:last_url])
|
839
875
|
# check for meta redirects, except for redirects back to the same page (infinite
|
840
876
|
# loop redirects).
|
841
877
|
metas=document_object.getElementsByTagName 'meta'
|
@@ -876,7 +912,11 @@ module Vapir
|
|
876
912
|
# - :format => a valid format. if :dc is :window, the default is 'png' ('jpeg' is also supported); if :dc is anything else, 'bmp' is both the
|
877
913
|
# default and the only supported format.
|
878
914
|
def screen_capture(filename, options = {})
|
879
|
-
|
915
|
+
if filename =~ /\.(\w+)\z/
|
916
|
+
extension = $1
|
917
|
+
file_format = %w(jpeg png).inject({'jpg' => 'jpeg'}){|h,f| h.merge(f => f) }[extension]
|
918
|
+
end
|
919
|
+
options = handle_options(options, :format => file_format, :dc => :page)
|
880
920
|
|
881
921
|
if options[:dc] == :page
|
882
922
|
options[:format] ||= 'png'
|
@@ -929,9 +969,8 @@ module Vapir
|
|
929
969
|
fileOutputStream.init(nsFile, writeFlag | createFlag | truncateFlag, 0664, null);
|
930
970
|
fileOutputStream.write(bytes, numBytes);
|
931
971
|
fileOutputStream.close();
|
932
|
-
document_element.removeChild(canvas);
|
933
972
|
}
|
934
|
-
|
973
|
+
finally
|
935
974
|
{ document_element.removeChild(canvas);
|
936
975
|
}
|
937
976
|
)
|
@@ -984,10 +1023,19 @@ module Vapir
|
|
984
1023
|
raise NotImplementedError, "(need to know how to access windows registry on JRuby)" if RUBY_PLATFORM =~ /java/
|
985
1024
|
require 'win32/registry'
|
986
1025
|
lm = ::Win32::Registry::HKEY_LOCAL_MACHINE
|
987
|
-
lm.open('SOFTWARE\Mozilla\Mozilla Firefox') do |
|
988
|
-
|
989
|
-
|
990
|
-
|
1026
|
+
lm.open('SOFTWARE\Mozilla\Mozilla Firefox') do |firefox_reg|
|
1027
|
+
firefox_reg.keys.map do |firefox_version_key|
|
1028
|
+
firefox_reg.open(firefox_version_key) do |firefox_version_reg|
|
1029
|
+
if firefox_version_reg.keys.include?('Main')
|
1030
|
+
firefox_version_reg.open('Main') do |firefox_version_main_reg|
|
1031
|
+
firefox_version_main_reg.map do |key, type, data|
|
1032
|
+
if key=='PathToExe'
|
1033
|
+
return data
|
1034
|
+
end
|
1035
|
+
end
|
1036
|
+
end
|
1037
|
+
end
|
1038
|
+
end
|
991
1039
|
end
|
992
1040
|
end
|
993
1041
|
end
|
@@ -60,7 +60,7 @@ module Vapir
|
|
60
60
|
# TODO: Provide ability to specify event parameters like keycode for key events, and click screen
|
61
61
|
# coordinates for mouse events.
|
62
62
|
def fire_event(event_type, options={})
|
63
|
-
options={:wait =>
|
63
|
+
options={:wait => config.wait, :highlight => true}.merge(options)
|
64
64
|
with_highlight(options) do
|
65
65
|
event=create_event_object(event_type, options)
|
66
66
|
if !options[:wait]
|
@@ -159,10 +159,10 @@ module Vapir
|
|
159
159
|
# Options:
|
160
160
|
# - :wait => true or false. If true, waits for the javascript call to return, and calls the #wait method.
|
161
161
|
# If false, does not wait for the javascript to return and does not call #wait.
|
162
|
-
# Default is true.
|
162
|
+
# Default is the current config.wait value (which is by default true).
|
163
163
|
# - :highlight => true or false. Highlights the element while clicking if true. Default is true.
|
164
164
|
def click(options={})
|
165
|
-
options={:wait =>
|
165
|
+
options={:wait => config.wait, :highlight => true}.merge(options)
|
166
166
|
result=nil
|
167
167
|
with_highlight(options) do
|
168
168
|
assert_enabled if respond_to?(:assert_enabled)
|
@@ -196,12 +196,12 @@ module Vapir
|
|
196
196
|
# Takes options:
|
197
197
|
# - :highlight => true or false. Highlights the element while clicking if true. Default is true.
|
198
198
|
def click_no_wait(options={})
|
199
|
-
|
199
|
+
with_config(:wait => false) { click(options) }
|
200
200
|
end
|
201
201
|
|
202
202
|
# Waits for the browser to finish loading, if it is loading. See Firefox#wait.
|
203
203
|
def wait(options={})
|
204
|
-
@container.wait(options)
|
204
|
+
@container.wait(options) if config.wait
|
205
205
|
end
|
206
206
|
|
207
207
|
# Checks this element and its parents for display: none or visibility: hidden, these are
|
@@ -240,7 +240,7 @@ class FirefoxSocket
|
|
240
240
|
# immediately.
|
241
241
|
def read_value(options={})
|
242
242
|
options=options_from_config(options, {:timeout => :default_timeout, :read_size => :read_size}, [:length_before_value])
|
243
|
-
received_data = []
|
243
|
+
# received_data = []
|
244
244
|
value_string = ""
|
245
245
|
size_to_read=options[:read_size]
|
246
246
|
timeout=options[:timeout]
|
@@ -249,7 +249,13 @@ class FirefoxSocket
|
|
249
249
|
# logger.add(-1) { "RECV_SOCKET is starting. timeout=#{timeout}" }
|
250
250
|
while size_to_read > 0 && ensuring_extra_handled { @socket.ready_to_recv?(timeout) }
|
251
251
|
data = ensuring_extra_handled { @socket.recv(size_to_read) }
|
252
|
-
|
252
|
+
|
253
|
+
# if the peer has performed an orderly shutdown, recv returns a 0-length string.
|
254
|
+
if data.size==0
|
255
|
+
raise FirefoxSocketConnectionError, "The connection to Firefox has been closed."
|
256
|
+
end
|
257
|
+
|
258
|
+
# received_data << data
|
253
259
|
value_string << data
|
254
260
|
if @prompt && @expecting_prompt && utf8_length_safe(value_string) > @prompt.length
|
255
261
|
if value_string =~ /\A#{Regexp.escape(@prompt)}/
|
@@ -280,11 +286,6 @@ class FirefoxSocket
|
|
280
286
|
timeout=config.short_timeout
|
281
287
|
end
|
282
288
|
end
|
283
|
-
|
284
|
-
# Kernel.select seems to indicate that a dead socket is ready to read, and returns endless blank strings to recv. rather irritating.
|
285
|
-
if received_data.length >= 3 && received_data[-3..-1].all?{|rd| rd==''}
|
286
|
-
raise FirefoxSocketConnectionError, "Socket seems to no longer be connected"
|
287
|
-
end
|
288
289
|
# logger.add(-1) { "RECV_SOCKET is continuing. timeout=#{timeout}; data=#{data.inspect}" }
|
289
290
|
end
|
290
291
|
# logger.debug { "RECV_SOCKET is done. received_data=#{received_data.inspect}; value_string=#{value_string.inspect}" }
|
@@ -143,7 +143,7 @@ class JavascriptObject
|
|
143
143
|
def val_or_object(options={})
|
144
144
|
options={:error_on_undefined=>true, :define_methods => self.class.always_define_methods}.merge(options)
|
145
145
|
if function_result # calling functions multiple times is bad, so store in temp before figuring out what to do with it
|
146
|
-
|
146
|
+
store_rand_temp.val_or_object(options.merge(:error_on_undefined => false))
|
147
147
|
else
|
148
148
|
# if we don't know our type, stick everything into one call to avoid multiple socket calls
|
149
149
|
types_to_convert = ['boolean', 'number', 'string', 'null']
|
@@ -192,7 +192,7 @@ class JavascriptObject
|
|
192
192
|
end
|
193
193
|
end
|
194
194
|
# does the work of #method_missing to determine whether to call a function what to return based
|
195
|
-
# on the defined behavior of the given suffix. see #method_missing for more
|
195
|
+
# on the defined behavior of the given suffix. see #method_missing for more information.
|
196
196
|
def assign_or_call_or_val_or_object_by_suffix(suffix, *args)
|
197
197
|
if suffix=='='
|
198
198
|
assign(*args)
|
@@ -472,7 +472,9 @@ class JavascriptObject
|
|
472
472
|
# in irb, mostly.
|
473
473
|
def define_methods! # :nodoc:
|
474
474
|
metaclass=(class << self; self; end)
|
475
|
-
|
475
|
+
# the following needs the try/catch because sometimes it raises NS_ERROR_NOT_AVAILABLE: Component is not available
|
476
|
+
# bug: https://bugzilla.mozilla.org/show_bug.cgi?id=683978
|
477
|
+
keys=firefox_socket.object("function(obj) { var keys=[]; try { for(var key in obj) { keys.push(key); } } catch(e) {} return keys; }").pass(self).val
|
476
478
|
|
477
479
|
keys.grep(/\A[a-z_][a-z0-9_]*\z/i).reject{|k| self.class.method_defined?(k)}.each do |key|
|
478
480
|
metaclass.send(:define_method, key) do |*args|
|
@@ -545,6 +547,9 @@ class JavascriptObject
|
|
545
547
|
def to_function
|
546
548
|
JavascriptFunction.new(self.ref, self.firefox_socket, :debug_name => debug_name)
|
547
549
|
end
|
550
|
+
def to_simple_enumerator
|
551
|
+
JavascriptSimpleEnumerator.new(self.ref, self.firefox_socket, :debug_name => debug_name)
|
552
|
+
end
|
548
553
|
|
549
554
|
# returns a ruby Hash. each key/value pair of this object
|
550
555
|
# is represented in the returned hash.
|
@@ -649,6 +654,7 @@ class JavascriptDOMNode < JavascriptObject
|
|
649
654
|
# call #dump(:recurse => n) to recurse down only n levels. default is to recurse all the way down the dom tree.
|
650
655
|
def dump(options={})
|
651
656
|
options={:recurse => nil, :level => 0}.merge(options)
|
657
|
+
options[:document] ||= self.ownerDocument
|
652
658
|
next_options=options.merge(:recurse => options[:recurse] && (options[:recurse]-1), :level => options[:level]+1)
|
653
659
|
result=(" "*options[:level]*2)+self.inspect+"\n"
|
654
660
|
if options[:recurse]==0
|
@@ -657,6 +663,13 @@ class JavascriptDOMNode < JavascriptObject
|
|
657
663
|
self.childNodes.to_array.each do |child|
|
658
664
|
result+=child.to_dom.dump(next_options)
|
659
665
|
end
|
666
|
+
anons = self.nodeType == 1 && options[:document].getAnonymousNodes(self)
|
667
|
+
if anons
|
668
|
+
result+=(" "*next_options[:level]*2)+"ANONYMOUS:\n"
|
669
|
+
anons.to_array.each do |child|
|
670
|
+
result+=child.to_dom.dump(next_options)
|
671
|
+
end
|
672
|
+
end
|
660
673
|
end
|
661
674
|
result
|
662
675
|
end
|
@@ -734,3 +747,13 @@ class JavascriptFunction < JavascriptObject
|
|
734
747
|
end
|
735
748
|
end
|
736
749
|
end
|
750
|
+
|
751
|
+
class JavascriptSimpleEnumerator < JavascriptObject
|
752
|
+
def each
|
753
|
+
stored = store_rand_temp
|
754
|
+
while stored.hasMoreElements
|
755
|
+
yield stored.getNext
|
756
|
+
end
|
757
|
+
end
|
758
|
+
include Enumerable
|
759
|
+
end
|
@@ -51,7 +51,7 @@ module Vapir
|
|
51
51
|
# raise if no anonymous nodes are found (this is where the buttons are)
|
52
52
|
anonymous_dialog_nodes=@modal_window.document.getAnonymousNodes(@modal_window.document.documentElement) || raise("Could not find anonymous nodes on which to look for buttons")
|
53
53
|
xul_buttons=[]
|
54
|
-
anonymous_dialog_nodes.to_array.each do |node|
|
54
|
+
anonymous_dialog_nodes.to_array.select{|node| node.nodeType == 1 }.each do |node|
|
55
55
|
xul_buttons+=node.getElementsByTagName('xul:button').to_array.select do |button|
|
56
56
|
Vapir::fuzzy_match(button.label, button_text)
|
57
57
|
end
|
@@ -74,8 +74,8 @@ module Vapir
|
|
74
74
|
assert_exists
|
75
75
|
modal_window
|
76
76
|
end
|
77
|
-
def
|
78
|
-
'MozillaDialogClass'
|
77
|
+
def mozilla_window_class_names
|
78
|
+
['MozillaDialogClass']
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
@@ -134,7 +134,8 @@ module Vapir
|
|
134
134
|
end
|
135
135
|
|
136
136
|
def wait(options=nil)
|
137
|
-
|
137
|
+
return unless config.wait
|
138
|
+
::Waiter.try_for(config.wait_timeout) do
|
138
139
|
!browser_object.webProgress.isLoadingDocument
|
139
140
|
end
|
140
141
|
end
|
@@ -11,10 +11,12 @@ module Vapir
|
|
11
11
|
end
|
12
12
|
|
13
13
|
# evaluates a given javascript string in the context of the browser's content window. anything
|
14
|
-
# that is a top-level variable on the window will be seen as a
|
15
|
-
# evaluated script.
|
14
|
+
# that is a top-level variable on the window (such as document or alert) will be seen as a
|
15
|
+
# top-level variable in the evaluated script.
|
16
16
|
#
|
17
|
-
# returns the last evaluated expression.
|
17
|
+
# returns the last evaluated expression. WARNING! DO NOT RUN #execute_script AGAINST UNTRUSTED
|
18
|
+
# PAGES! the resulting value has no security wrappers and could execute malicious code in a
|
19
|
+
# privileged context.
|
18
20
|
#
|
19
21
|
# raises an error if the given javascript errors.
|
20
22
|
#
|
@@ -43,8 +45,17 @@ module Vapir
|
|
43
45
|
# >> browser.execute_script('element.PercentLoaded()', :element => browser.element(:tag_name => 'embed').element_object)
|
44
46
|
# => 100
|
45
47
|
def execute_script(javascript, other_variables={})
|
46
|
-
|
47
|
-
|
48
|
+
# TODO: add tests for cross-context expando properties
|
49
|
+
xpcNativeWrapper = firefox_socket.root['XPCNativeWrapper']
|
50
|
+
unwrapped_window = if xpcNativeWrapper.respond_to?('unwrap')
|
51
|
+
xpcNativeWrapper.unwrap(content_window_object)
|
52
|
+
elsif content_window_object.respond_to?('wrappedJSObject')
|
53
|
+
content_window_object.wrappedJSObject
|
54
|
+
else
|
55
|
+
content_window_object.window
|
56
|
+
end
|
57
|
+
sandbox=firefox_socket.Components.utils.Sandbox(unwrapped_window, :wantXrays => false)
|
58
|
+
sandbox.window = unwrapped_window
|
48
59
|
other_variables.each do |name, var|
|
49
60
|
sandbox[name]=var
|
50
61
|
end
|
data/lib/vapir-firefox/window.rb
CHANGED
@@ -18,7 +18,7 @@ module Vapir
|
|
18
18
|
begin
|
19
19
|
candidates=::Waiter.try_for(2, :condition => proc{|ret| ret.size > 0}, :exception => nil) do
|
20
20
|
WinWindow::All.select do |win|
|
21
|
-
|
21
|
+
mozilla_window_class_names.include?(win.class_name) && win.text==browser_window_object.document.title
|
22
22
|
end
|
23
23
|
end
|
24
24
|
unless candidates.size==1
|
metadata
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vapir-firefox
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: 51
|
5
4
|
prerelease: false
|
6
5
|
segments:
|
7
6
|
- 1
|
8
|
-
-
|
7
|
+
- 10
|
9
8
|
- 0
|
10
|
-
version: 1.
|
9
|
+
version: 1.10.0
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- Ethan
|
@@ -15,34 +14,30 @@ autorequire:
|
|
15
14
|
bindir: bin
|
16
15
|
cert_chain: []
|
17
16
|
|
18
|
-
date: 2011-
|
17
|
+
date: 2011-09-28 00:00:00 -04:00
|
19
18
|
default_executable:
|
20
19
|
dependencies:
|
21
20
|
- !ruby/object:Gem::Dependency
|
22
21
|
name: vapir-common
|
23
22
|
prerelease: false
|
24
23
|
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
24
|
requirements:
|
27
25
|
- - "="
|
28
26
|
- !ruby/object:Gem::Version
|
29
|
-
hash: 51
|
30
27
|
segments:
|
31
28
|
- 1
|
32
|
-
-
|
29
|
+
- 10
|
33
30
|
- 0
|
34
|
-
version: 1.
|
31
|
+
version: 1.10.0
|
35
32
|
type: :runtime
|
36
33
|
version_requirements: *id001
|
37
34
|
- !ruby/object:Gem::Dependency
|
38
35
|
name: json
|
39
36
|
prerelease: false
|
40
37
|
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
38
|
requirements:
|
43
39
|
- - ">="
|
44
40
|
- !ruby/object:Gem::Version
|
45
|
-
hash: 3
|
46
41
|
segments:
|
47
42
|
- 0
|
48
43
|
version: "0"
|
@@ -109,27 +104,23 @@ rdoc_options:
|
|
109
104
|
require_paths:
|
110
105
|
- lib
|
111
106
|
required_ruby_version: !ruby/object:Gem::Requirement
|
112
|
-
none: false
|
113
107
|
requirements:
|
114
108
|
- - ">="
|
115
109
|
- !ruby/object:Gem::Version
|
116
|
-
hash: 3
|
117
110
|
segments:
|
118
111
|
- 0
|
119
112
|
version: "0"
|
120
113
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
121
|
-
none: false
|
122
114
|
requirements:
|
123
115
|
- - ">="
|
124
116
|
- !ruby/object:Gem::Version
|
125
|
-
hash: 3
|
126
117
|
segments:
|
127
118
|
- 0
|
128
119
|
version: "0"
|
129
120
|
requirements:
|
130
121
|
- Firefox browser with MozRepl or JSSH extension installed
|
131
122
|
rubyforge_project:
|
132
|
-
rubygems_version: 1.3.
|
123
|
+
rubygems_version: 1.3.6
|
133
124
|
signing_key:
|
134
125
|
specification_version: 3
|
135
126
|
summary: Library for automating the Firefox browser in Ruby
|