1 package playwright
2
3 import (
4 "fmt"
5 "io/ioutil"
6 "sync"
7 "time"
8 )
9
10 type frameImpl struct {
11 channelOwner
12 sync.RWMutex
13 detached bool
14 page *pageImpl
15 name string
16 url string
17 parentFrame Frame
18 childFrames []Frame
19 loadStates *safeStringSet
20 }
21
22 func newFrame(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *frameImpl {
23 var loadStates *safeStringSet
24 if ls, ok := initializer["loadStates"].([]string); ok {
25 loadStates = newSafeStringSet(ls)
26 } else {
27 loadStates = newSafeStringSet([]string{})
28 }
29 bt := &frameImpl{
30 name: initializer["name"].(string),
31 url: initializer["url"].(string),
32 loadStates: loadStates,
33 childFrames: make([]Frame, 0),
34 }
35 bt.createChannelOwner(bt, parent, objectType, guid, initializer)
36
37 channelOwner := fromNullableChannel(initializer["parentFrame"])
38 if channelOwner != nil {
39 bt.parentFrame = channelOwner.(*frameImpl)
40 bt.parentFrame.(*frameImpl).childFrames = append(bt.parentFrame.(*frameImpl).childFrames, bt)
41 }
42
43 bt.channel.On("navigated", bt.onFrameNavigated)
44 bt.channel.On("loadstate", bt.onLoadState)
45 return bt
46 }
47
48 func (f *frameImpl) URL() string {
49 f.RLock()
50 defer f.RUnlock()
51 return f.url
52 }
53
54 func (f *frameImpl) Name() string {
55 f.RLock()
56 defer f.RUnlock()
57 return f.name
58 }
59
60 func (f *frameImpl) SetContent(content string, options ...PageSetContentOptions) error {
61 _, err := f.channel.Send("setContent", map[string]interface{}{
62 "html": content,
63 }, options)
64 return err
65 }
66
67 func (f *frameImpl) Content() (string, error) {
68 content, err := f.channel.Send("content")
69 return content.(string), err
70 }
71
72 func (f *frameImpl) Goto(url string, options ...PageGotoOptions) (Response, error) {
73 channel, err := f.channel.Send("goto", map[string]interface{}{
74 "url": url,
75 }, options)
76 if err != nil {
77 return nil, err
78 }
79 channelOwner := fromNullableChannel(channel)
80 if channelOwner == nil {
81 return nil, nil
82 }
83 return channelOwner.(*responseImpl), nil
84 }
85
86 func (f *frameImpl) AddScriptTag(options PageAddScriptTagOptions) (ElementHandle, error) {
87 if options.Path != nil {
88 file, err := ioutil.ReadFile(*options.Path)
89 if err != nil {
90 return nil, err
91 }
92 options.Content = String(string(file))
93 options.Path = nil
94 }
95 channel, err := f.channel.Send("addScriptTag", options)
96 if err != nil {
97 return nil, err
98 }
99 return fromChannel(channel).(*elementHandleImpl), nil
100 }
101
102 func (f *frameImpl) AddStyleTag(options PageAddStyleTagOptions) (ElementHandle, error) {
103 if options.Path != nil {
104 file, err := ioutil.ReadFile(*options.Path)
105 if err != nil {
106 return nil, err
107 }
108 options.Content = String(string(file))
109 options.Path = nil
110 }
111 channel, err := f.channel.Send("addStyleTag", options)
112 if err != nil {
113 return nil, err
114 }
115 return fromChannel(channel).(*elementHandleImpl), nil
116 }
117
118 func (f *frameImpl) Page() Page {
119 return f.page
120 }
121
122 func (f *frameImpl) WaitForLoadState(given ...string) {
123 state := "load"
124 if len(given) == 1 {
125 state = given[0]
126 }
127 if f.loadStates.Has(state) {
128 return
129 }
130 succeed := make(chan bool, 1)
131 f.Once("loadstate", func(ev ...interface{}) {
132 gotState := ev[0].(string)
133 if gotState == state {
134 succeed <- true
135 }
136 })
137 <-succeed
138 }
139
140 func (f *frameImpl) WaitForURL(url string, options ...FrameWaitForURLOptions) error {
141 if len(options) > 0 {
142 if _, err := f.WaitForNavigation(PageWaitForNavigationOptions{
143 URL: url,
144 Timeout: options[0].Timeout,
145 WaitUntil: options[0].WaitUntil,
146 }); err != nil {
147 return err
148 }
149 }
150 return nil
151 }
152
153 func (f *frameImpl) WaitForEvent(event string, predicate ...interface{}) interface{} {
154 return <-waitForEvent(f, event, predicate...)
155 }
156
157 func (f *frameImpl) WaitForNavigation(options ...PageWaitForNavigationOptions) (Response, error) {
158 option := PageWaitForNavigationOptions{}
159 if len(options) == 1 {
160 option = options[0]
161 }
162 if option.WaitUntil == nil {
163 option.WaitUntil = WaitUntilStateLoad
164 }
165 if option.Timeout == nil {
166 option.Timeout = Float(f.page.timeoutSettings.NavigationTimeout())
167 }
168 deadline := time.After(time.Duration(*option.Timeout) * time.Millisecond)
169 var matcher *urlMatcher
170 if option.URL != nil {
171 matcher = newURLMatcher(option.URL)
172 }
173 predicate := func(events ...interface{}) bool {
174 ev := events[0].(map[string]interface{})
175 if ev["error"] != nil {
176 print("error")
177 }
178 return matcher == nil || matcher.Matches(ev["url"].(string))
179 }
180 select {
181 case <-deadline:
182 return nil, fmt.Errorf("Timeout %.2fms exceeded.", *option.Timeout)
183 case eventData := <-waitForEvent(f, "navigated", predicate):
184 event := eventData.(map[string]interface{})
185 if event["newDocument"] != nil && event["newDocument"].(map[string]interface{})["request"] != nil {
186 request := fromChannel(event["newDocument"].(map[string]interface{})["request"]).(*requestImpl)
187 return request.Response()
188 }
189 }
190 return nil, nil
191 }
192
193 func (f *frameImpl) onFrameNavigated(ev map[string]interface{}) {
194 f.Lock()
195 f.url = ev["url"].(string)
196 f.name = ev["name"].(string)
197 f.Unlock()
198 f.Emit("navigated", ev)
199 if f.page != nil {
200 f.page.Emit("framenavigated", f)
201 }
202 }
203
204 func (f *frameImpl) onLoadState(ev map[string]interface{}) {
205 if ev["add"] != nil {
206 add := ev["add"].(string)
207 f.loadStates.Add(add)
208 f.Emit("loadstate", add)
209 } else if ev["remove"] != nil {
210 remove := ev["remove"].(string)
211 f.loadStates.Remove(remove)
212 }
213 }
214
215 func (f *frameImpl) QuerySelector(selector string) (ElementHandle, error) {
216 channel, err := f.channel.Send("querySelector", map[string]interface{}{
217 "selector": selector,
218 })
219 if err != nil {
220 return nil, err
221 }
222 if channel == nil {
223 return nil, nil
224 }
225 return fromChannel(channel).(*elementHandleImpl), nil
226 }
227
228 func (f *frameImpl) QuerySelectorAll(selector string) ([]ElementHandle, error) {
229 channels, err := f.channel.Send("querySelectorAll", map[string]interface{}{
230 "selector": selector,
231 })
232 if err != nil {
233 return nil, err
234 }
235 elements := make([]ElementHandle, 0)
236 for _, channel := range channels.([]interface{}) {
237 elements = append(elements, fromChannel(channel).(*elementHandleImpl))
238 }
239 return elements, nil
240 }
241
242 func (f *frameImpl) Evaluate(expression string, options ...interface{}) (interface{}, error) {
243 var arg interface{}
244 forceExpression := false
245 if !isFunctionBody(expression) {
246 forceExpression = true
247 }
248 if len(options) == 1 {
249 arg = options[0]
250 } else if len(options) == 2 {
251 arg = options[0]
252 forceExpression = options[1].(bool)
253 }
254 result, err := f.channel.Send("evaluateExpression", map[string]interface{}{
255 "expression": expression,
256 "isFunction": !forceExpression,
257 "arg": serializeArgument(arg),
258 })
259 if err != nil {
260 return nil, err
261 }
262 return parseResult(result), nil
263 }
264
265 func (f *frameImpl) EvalOnSelector(selector string, expression string, options ...interface{}) (interface{}, error) {
266 var arg interface{}
267 forceExpression := false
268 if !isFunctionBody(expression) {
269 forceExpression = true
270 }
271 if len(options) == 1 {
272 arg = options[0]
273 } else if len(options) == 2 {
274 arg = options[0]
275 forceExpression = options[1].(bool)
276 }
277 result, err := f.channel.Send("evalOnSelector", map[string]interface{}{
278 "selector": selector,
279 "expression": expression,
280 "isFunction": !forceExpression,
281 "arg": serializeArgument(arg),
282 })
283 if err != nil {
284 return nil, err
285 }
286 return parseResult(result), nil
287 }
288
289 func (f *frameImpl) EvalOnSelectorAll(selector string, expression string, options ...interface{}) (interface{}, error) {
290 var arg interface{}
291 forceExpression := false
292 if !isFunctionBody(expression) {
293 forceExpression = true
294 }
295 if len(options) == 1 {
296 arg = options[0]
297 } else if len(options) == 2 {
298 arg = options[0]
299 forceExpression = options[1].(bool)
300 }
301 result, err := f.channel.Send("evalOnSelectorAll", map[string]interface{}{
302 "selector": selector,
303 "expression": expression,
304 "isFunction": !forceExpression,
305 "arg": serializeArgument(arg),
306 })
307 if err != nil {
308 return nil, err
309 }
310 return parseResult(result), nil
311 }
312
313 func (f *frameImpl) EvaluateHandle(expression string, options ...interface{}) (JSHandle, error) {
314 var arg interface{}
315 forceExpression := false
316 if !isFunctionBody(expression) {
317 forceExpression = true
318 }
319 if len(options) == 1 {
320 arg = options[0]
321 } else if len(options) == 2 {
322 arg = options[0]
323 forceExpression = options[1].(bool)
324 }
325 result, err := f.channel.Send("evaluateExpressionHandle", map[string]interface{}{
326 "expression": expression,
327 "isFunction": !forceExpression,
328 "arg": serializeArgument(arg),
329 })
330 if err != nil {
331 return nil, err
332 }
333 channelOwner := fromChannel(result)
334 if channelOwner == nil {
335 return nil, nil
336 }
337 return channelOwner.(JSHandle), nil
338 }
339
340 func (f *frameImpl) Click(selector string, options ...PageClickOptions) error {
341 _, err := f.channel.Send("click", map[string]interface{}{
342 "selector": selector,
343 }, options)
344 return err
345 }
346
347 func (f *frameImpl) WaitForSelector(selector string, options ...PageWaitForSelectorOptions) (ElementHandle, error) {
348 channel, err := f.channel.Send("waitForSelector", map[string]interface{}{
349 "selector": selector,
350 }, options)
351 if err != nil {
352 return nil, err
353 }
354 channelOwner := fromNullableChannel(channel)
355 if channelOwner == nil {
356 return nil, nil
357 }
358 return channelOwner.(*elementHandleImpl), nil
359 }
360
361 func (f *frameImpl) DispatchEvent(selector, typ string, eventInit interface{}, options ...PageDispatchEventOptions) error {
362 _, err := f.channel.Send("dispatchEvent", map[string]interface{}{
363 "selector": selector,
364 "type": typ,
365 "eventInit": serializeArgument(eventInit),
366 })
367 return err
368 }
369
370 func (f *frameImpl) InnerText(selector string, options ...PageInnerTextOptions) (string, error) {
371 innerText, err := f.channel.Send("innerText", map[string]interface{}{
372 "selector": selector,
373 }, options)
374 if err != nil {
375 return "", err
376 }
377 return innerText.(string), nil
378 }
379
380 func (f *frameImpl) InnerHTML(selector string, options ...PageInnerHTMLOptions) (string, error) {
381 innerHTML, err := f.channel.Send("innerHTML", map[string]interface{}{
382 "selector": selector,
383 }, options)
384 if err != nil {
385 return "", err
386 }
387 return innerHTML.(string), nil
388 }
389
390 func (f *frameImpl) GetAttribute(selector string, name string, options ...PageGetAttributeOptions) (string, error) {
391 attribute, err := f.channel.Send("getAttribute", map[string]interface{}{
392 "selector": selector,
393 "name": name,
394 }, options)
395 if err != nil {
396 return "", err
397 }
398 if attribute == nil {
399 return "", nil
400 }
401 return attribute.(string), nil
402 }
403
404 func (f *frameImpl) Hover(selector string, options ...PageHoverOptions) error {
405 _, err := f.channel.Send("hover", map[string]interface{}{
406 "selector": selector,
407 }, options)
408 return err
409 }
410
411 func (f *frameImpl) SetInputFiles(selector string, files []InputFile, options ...FrameSetInputFilesOptions) error {
412 _, err := f.channel.Send("setInputFiles", map[string]interface{}{
413 "selector": selector,
414 "files": normalizeFilePayloads(files),
415 }, options)
416 return err
417 }
418
419 func (f *frameImpl) Type(selector, text string, options ...PageTypeOptions) error {
420 _, err := f.channel.Send("type", map[string]interface{}{
421 "selector": selector,
422 "text": text,
423 }, options)
424 return err
425 }
426
427 func (f *frameImpl) Press(selector, key string, options ...PagePressOptions) error {
428 _, err := f.channel.Send("press", map[string]interface{}{
429 "selector": selector,
430 "key": key,
431 }, options)
432 return err
433 }
434
435 func (f *frameImpl) Check(selector string, options ...FrameCheckOptions) error {
436 _, err := f.channel.Send("check", map[string]interface{}{
437 "selector": selector,
438 }, options)
439 return err
440 }
441
442 func (f *frameImpl) Uncheck(selector string, options ...FrameUncheckOptions) error {
443 _, err := f.channel.Send("uncheck", map[string]interface{}{
444 "selector": selector,
445 }, options)
446 return err
447 }
448
449 func (f *frameImpl) WaitForTimeout(timeout float64) {
450 time.Sleep(time.Duration(timeout) * time.Millisecond)
451 }
452
453 func (f *frameImpl) WaitForFunction(expression string, arg interface{}, options ...FrameWaitForFunctionOptions) (JSHandle, error) {
454 var option FrameWaitForFunctionOptions
455 if len(options) == 1 {
456 option = options[0]
457 }
458 forceExpression := false
459 if !isFunctionBody(expression) {
460 forceExpression = true
461 }
462 result, err := f.channel.Send("waitForFunction", map[string]interface{}{
463 "expression": expression,
464 "isFunction": !forceExpression,
465 "arg": serializeArgument(arg),
466 "timeout": option.Timeout,
467 "polling": option.Polling,
468 })
469 if err != nil {
470 return nil, err
471 }
472 handle := fromChannel(result)
473 if handle == nil {
474 return nil, nil
475 }
476 return handle.(*jsHandleImpl), nil
477 }
478
479 func (f *frameImpl) Title() (string, error) {
480 title, err := f.channel.Send("title")
481 if err != nil {
482 return "", err
483 }
484 return title.(string), err
485 }
486
487 func (f *frameImpl) ChildFrames() []Frame {
488 return f.childFrames
489 }
490
491 func (f *frameImpl) Dblclick(selector string, options ...FrameDblclickOptions) error {
492 _, err := f.channel.Send("dblclick", map[string]interface{}{
493 "selector": selector,
494 }, options)
495 return err
496 }
497
498 func (f *frameImpl) Fill(selector string, value string, options ...FrameFillOptions) error {
499 _, err := f.channel.Send("fill", map[string]interface{}{
500 "selector": selector,
501 "value": value,
502 }, options)
503 return err
504 }
505
506 func (f *frameImpl) Focus(selector string, options ...FrameFocusOptions) error {
507 _, err := f.channel.Send("focus", map[string]interface{}{
508 "selector": selector,
509 }, options)
510 return err
511 }
512
513 func (f *frameImpl) FrameElement() (ElementHandle, error) {
514 elementHandle, err := f.channel.Send("frameElement")
515 if err != nil {
516 return nil, err
517 }
518 return elementHandle.(*elementHandleImpl), nil
519 }
520
521 func (f *frameImpl) IsDetached() bool {
522 return f.detached
523 }
524
525 func (f *frameImpl) ParentFrame() Frame {
526 return f.parentFrame
527 }
528
529 func (f *frameImpl) TextContent(selector string, options ...FrameTextContentOptions) (string, error) {
530 textContent, err := f.channel.Send("textContent", map[string]interface{}{
531 "selector": selector,
532 }, options)
533 if err != nil {
534 return "", err
535 }
536 return textContent.(string), nil
537 }
538
539 func (f *frameImpl) Tap(selector string, options ...FrameTapOptions) error {
540 _, err := f.channel.Send("tap", map[string]interface{}{
541 "selector": selector,
542 }, options)
543 return err
544 }
545
546 func (f *frameImpl) SelectOption(selector string, values SelectOptionValues, options ...FrameSelectOptionOptions) ([]string, error) {
547 opts := convertSelectOptionSet(values)
548
549 m := make(map[string]interface{})
550 m["selector"] = selector
551 for k, v := range opts {
552 m[k] = v
553 }
554 selected, err := f.channel.Send("selectOption", m, options)
555 if err != nil {
556 return nil, err
557 }
558
559 return transformToStringList(selected), nil
560 }
561
562 func (f *frameImpl) IsChecked(selector string, options ...FrameIsCheckedOptions) (bool, error) {
563 checked, err := f.channel.Send("isChecked", map[string]interface{}{
564 "selector": selector,
565 }, options)
566 if err != nil {
567 return false, err
568 }
569 return checked.(bool), nil
570 }
571
572 func (f *frameImpl) IsDisabled(selector string, options ...FrameIsDisabledOptions) (bool, error) {
573 disabled, err := f.channel.Send("isDisabled", map[string]interface{}{
574 "selector": selector,
575 }, options)
576 if err != nil {
577 return false, err
578 }
579 return disabled.(bool), nil
580 }
581
582 func (f *frameImpl) IsEditable(selector string, options ...FrameIsEditableOptions) (bool, error) {
583 editable, err := f.channel.Send("isEditable", map[string]interface{}{
584 "selector": selector,
585 }, options)
586 if err != nil {
587 return false, err
588 }
589 return editable.(bool), nil
590 }
591
592 func (f *frameImpl) IsEnabled(selector string, options ...FrameIsEnabledOptions) (bool, error) {
593 enabled, err := f.channel.Send("isEnabled", map[string]interface{}{
594 "selector": selector,
595 }, options)
596 if err != nil {
597 return false, err
598 }
599 return enabled.(bool), nil
600 }
601
602 func (f *frameImpl) IsHidden(selector string, options ...FrameIsHiddenOptions) (bool, error) {
603 hidden, err := f.channel.Send("isHidden", map[string]interface{}{
604 "selector": selector,
605 }, options)
606 if err != nil {
607 return false, err
608 }
609 return hidden.(bool), nil
610 }
611
612 func (f *frameImpl) IsVisible(selector string, options ...FrameIsVisibleOptions) (bool, error) {
613 visible, err := f.channel.Send("isVisible", map[string]interface{}{
614 "selector": selector,
615 }, options)
616 if err != nil {
617 return false, err
618 }
619 return visible.(bool), nil
620 }
621
622 func (f *frameImpl) InputValue(selector string, options ...FrameInputValueOptions) (string, error) {
623
624 value, err := f.channel.Send("inputValue", map[string]interface{}{
625 "selector": selector,
626 }, options)
627 return value.(string), err
628 }
629
630 func (f *frameImpl) DragAndDrop(source, target string, options ...FrameDragAndDropOptions) error {
631 _, err := f.channel.Send("dragAndDrop", map[string]interface{}{
632 "source": source,
633 "target": target,
634 }, options)
635 return err
636 }
637
638 func (f *frameImpl) SetChecked(selector string, checked bool, options ...FrameSetCheckedOptions) error {
639 if checked {
640 _, err := f.channel.Send("check", map[string]interface{}{
641 "selector": selector,
642 }, options)
643 return err
644 } else {
645 _, err := f.channel.Send("uncheck", map[string]interface{}{
646 "selector": selector,
647 }, options)
648 return err
649 }
650 }
651
652 func (f *frameImpl) Locator(selector string, options ...FrameLocatorOptions) (Locator, error) {
653 var option LocatorLocatorOptions
654 if len(options) == 1 {
655 option = LocatorLocatorOptions(options[0])
656 }
657 return newLocator(f, selector, option)
658 }
659
660 func (f *frameImpl) highlight(selector string) error {
661 _, err := f.channel.Send("highlight", map[string]interface{}{
662 "selector": selector,
663 })
664 return err
665 }
666
667 func (f *frameImpl) queryCount(selector string) (int, error) {
668 response, err := f.channel.Send("queryCount", map[string]interface{}{
669 "selector": selector,
670 })
671 if err != nil {
672 return 0, err
673 }
674 return int(response.(float64)), nil
675 }
676
View as plain text